26/12/2012

CSRFing the Web...

Introduction

Nowadays hacking, as already mentioned in my previous articles, has been industrialized, meaning that professional hackers are constantly hired to make money out of practically anything and therefore all Web Application vulnerabilities have to be understood and defeated.

This article is going to talk about what Cross Site Request Forgery (CSRF) is, explain how can someone perform a successful CSRF attack and describe how to amplify a CSRF attack (e.g. combine CSRF with other vulnerabilities). CSRF is an attack which forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated (simplistically speaking). With a little help from social engineering (like sending a link via email/chat), an attacker may force the users of a web application to execute actions of the attacker's choosing.

A successful CSRF exploit can compromise end user data and operation in case of a normal user. If the targeted end user is the administrator account, this can compromise the entire web application. More specifically CSRF is a Web Application vulnerability that has to exploit more than one design flaws in order to be successful. The design flaws that a CSRF attack can take advantage of are:
  1. Input Validation (e.g. Convert POST to GET) 
  2. Access Control (e.g. Session Fixation) 
  3. Privilege Assignment (e.g. Horizontal Privilege Escalation)
Note: Of course depending on the situation other type of vulnerabilities can be combined with a CSRF as part of a post exploitation process such as SQL Injection (e.g. SQL Inject the cookie and get access to valid cookie repository in the database).

History of CSRF

CSRF vulnerabilities have been known and in some cases exploited since 2001. Because it is carried out from the user's IP address, some website logs might not have evidence of CSRF. Exploits are under-reported, at least publicly, and as of 2007 there are few well-documented examples. About 18 million users of eBay's Internet Auction Co. at Auction.co.kr in Korea lost personal information in February 2008. Customers of a bank in Mexico were attacked in early 2008 with an image tag in email. The link in the image tag changed the DNS entry for the bank in their ADSL router to point to a malicious website impersonating the bank.

Severity of CSRF

According to the United States Department Of Homeland Security the most dangerous CSRF vulnerability ranks in at the 909th most dangerous software bug ever found. Other severity metrics have been issued for CSRF vulnerabilities that result in remote code execution with root privileges as well as a vulnerability that can compromise a root certificate, which will completely undermine a public key infrastructure.

But what exactly is a CSRF

CSRF is a form of confused deputy attack. Imagine you’re a malcontent who wants to harm another person in a maximum security jail. You’re probably going to have a tough time reaching that person due to your lack of proper credentials. A potentially easier approach to accomplish your misdeed is to confuse a deputy to misuse his authority to commit the dastardly act on your behalf. That’s a much more effective strategy for causing mayhem.

In the case of a CSRF attack, the confused deputy is your browser. After logging into a website, the website will issue your browser an authentication token within a cookie (well not always). Within each subsequent http POST or GET requests send, the cookie bind to the request will let the site know that you are authorized to take whatever action you’re taking. Here I am referring to a typical authentication and authorization scheme that most Web Application use.

Suppose you visit a malicious website soon after visiting your bank website or visit another website while being logged to your bank web account. Your session on the previous site might still be valid (btw please de-validate session before closing the browser). Thus, visiting a carefully crafted malicious website (perhaps you clicked on a spam link) could cause an Html form post to the previous website. Your browser would send the authentication cookie back to that site and appear to be making a request on your behalf, even though you did not intend to do so.

Yes but what is a CSRF

A CSRF is a POST or GET http request that when send to the vulnerable Web Application under certain conditions can cause the Web Application to perform an action on behalf of the user. Now meaningful CSRF attacks are those that can cause loss of Integrity or Confidentiality or Availability of the victim user data. For example if an e-Banking Web site is vulnerable to CSRF and the function of the Web Site that is vulnerable is responsible for transferring money, then this is a CSRF with high severity and should be fixed.

This is an example of a simple CSRF:

http://www.vulnerable.com/?transferEuros=3000?maliciousUserAccount=9832487   

Note: The link displayed above when clicked can authorize a malicious user to transfer 3000 euros from of the victim user account to the malicious user account with id 9832487, assuming of course that no proper counter measures have been taken.

The following diagram shows how can this happen more analytically:   




Note: The diagram above shows the steps an attacker can take to exploit the vulnerability (step 4 designtes the execution of the CSRF payload that performs the malicious action). It is pretty much similar to a Cross Site Script attack scenario. An attacker sends an e-mail to an Html enabled e-mail client that contains some sample images deliberately uploaded to a malicious server (controlled by the attacker), along with the malicious URL (or a malicious html form) that performs the CSRF function, waits until the user opens the e-mail and downloads the images or sets his/her e-mail to receive a notification when the victim user reads his/her e-mail. Thens he/she waits infront of the logs of the malicious image server or waits to receive a read e-mail receipt in his/her mailbox. After the image is downloaded or the read receipt is received he/she will try to verify that the malicious function was executed. Another scenario would be to calculate what times user interact with the web site and calculate the attack times before sending the malicious URL/Html form.

The diagram above explains that the CSRF (meaning the vulnerable link described previously) can be injected into an HTML enabled e-mail and be executed by a legitimate user. Now if the link (or else the CSRF vulnerable link) is bind to the Web Application session (which it should be) then the victim user would have to be logged to the vulnerable Web Application for the attack to be successful. If the link is not bind to the Web Application session then the this is not a CSRF vulnerability, is an Insecure Direct Object References vulnerability or Failure to Restrict URL Access also described by OWASP top 10 chart. Both vulnerabilities have to do with inappropriate access control and are completely irrelevant to CSRF or CSRF like vulnerabilities.

Now that you got a better grasp of what a CSRF attack is I can be more technical and explain more on how a CSRF attack look like by using http requests. So again the link described above looks as a Http request like that:

GET /homepage/transferEuros=3000?maliciousUserAccount=9832487 HTTP/1.1
Host: victim.com
Keep-Alive: timeout=15
Connection: Keep-Alive
Cookie: Authentication-Token
Accept: */*

Note: The vulnerable link when clicked will generate the GET request shown above and will, if it is successful, generate a 200 Http response message saying that the transaction was completed successfully.

Explaining more what a CSRF is

The following diagram shows thoroughly how a CSRF can be exploited:



Step 1: Mallory sends a phishing email to Bob, inviting him to visit her web server in order, for example, to win an iPhone 5. She has already created a web page at her web server with a hidden request to the Web Application where Bob is logged in. She has added some buttons to lure the victim in order to click on her page and win the iPhone!

Step 2: Bob visits the page at Mallory's Web server. Maybe he is greedy or he may not, however he clicks on the button in order to win the iPhone!...

Step 3: The forged request is "legitimized" with Bob's logged-in session and is executed at the web application.

A real-world analogy would be the following: Mallory presented a bank cheque to Bob and Bob puts under his name and signature, but haven't examined what sum of money is written on the cheque.In the following attack scenario, we can see how a malicious user can add a user to a web application just by fooling a logged-in administrator to click on a link.

A different approach to CSRF

Now that I explained a simple CSRF attack it is time to explain a more advanced scenario on how to exploit a CSRF. A CSRF most of the time is not easily recognizable and that is why lots of people cannot identify a CSRF unless it is really obvious, just like the one I just described. A CSRF issue raises when:
  1. A Web Application performs critical functions using GET Http requests (e.g. to transfer money, add users by just clicking a link etc).
  2. Does not distinguish between POST and GET requests (e.g. a Html form can be easily converted into a GET request, meaning that a Html POST request can be converted to a link etc). 
  3. Has a loose association or else not tight access control (e.g. does not use AntiCSRF tokens, is vulnerable to session fixation e.t.c).
  4. Is vulnerable to Cross Site Scripting (e.g. someone can use JavaScript to formate a valid Html POST form by using the XMLHTTP object along with an auto submit script etc). 
  5. The application is passing the session to the URL along with the AntiCSRF token.
  6. The session can be fixated and the AntiCSRF token is predictable or static.
Note: There are a lot more ways to perform a CSRF attack, but there are out of scope.

CSRF and POST to GET Interchange

It is common knowledge that when the Web Application does not distinguish between POST and GET requests an attacker can convert a POST Http request to a GET Http request and generate a link equivalent to the one described previously. Burp Suite does that automatically that from the proxy tab by right clicking the request and doing a change method (it also recalculates the Http request size in the content size field).

The attack just described is can be enhanced by using an auto submit script such as this one:

"JavaScript"> setTimeout('document.CSRFHtmlForm.submit()',5000);

Note: A very useful tool is the CSRF PoC tool also found in Burp Suite. Burp Suit CSRF PoC will generate a quick CSRF PoC for you (most of the time you would have to modify that to be realistic).

CSRF and Cross Site Scripting (XSS)

Cross-Site Scripting (XSS) attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user in the output it generates without validating or encoding it.

An attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not be trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by your browser and used with that site. These scripts can even rewrite the content of the HTML page. But can also inject an Html form with an auto submit script to execute the malicious CSRF. The example is very easy to understand so I wont have to give an example.

Note1: You can see how an XSS vulnerability can be combined with a CSRF  attack at the CSRF tool section (e.g. by injection also the auto submit javascript code along with the CSRF).

Note2: Of course an XSS can be combined with a CSRF attack using the XMLHTTP and auto submit javascript features. A very good XSS (XMLHTTP)/CSRF example can be found here. The specific post explains an XSS/CSRF bug found in gmail.

CSRF and Session Fixation

Session Fixation is an attack that permits an attacker to hijack a valid user session. The attack explores a limitation in the way the web application manages the session ID, more specifically the vulnerable web application. When authenticating a user, it doesn’t assign a new session ID, making it possible to use an existent session ID. The attack consists of inducing a user to authenticate himself with a known session ID, and then hijacking the user-validated session by the knowledge of the used session ID. The attacker has to provide a legitimate Web application session ID and try to make the victim's browser use it.

The session fixation attack is a class of Session Hijacking, which steals the established session between the client and the Web Server after the user logs in. Instead, the Session Fixation attack fixes an established session on the victim's browser, so the attack starts before the user logs in. There are several techniques to execute the attack; it depends on how the Web application deals with session tokens. Below are some of the most common technique:
  • Session token in the URL argument: The Session ID is sent to the victim in a hyperlink and the victim accesses the site through the malicious URL.
  • Session token in a hidden form field: In this method, the victim must be tricked to authenticate in the target Web Server, using a login form developed for the attacker. The form could be hosted in the evil web server or directly in html formatted e-mail.
  • Session ID in a cookie:
    • Client-side script:
      • Most browsers support the execution of client-side scripting. In this case, the aggressor could use attacks of code injection as the XSS (Cross-site scripting) attack to insert a malicious code in the hyperlink sent to the victim and fix a Session ID in its cookie. Using the function document.cookie, the browser which executes the command becomes capable of fixing values inside of the cookie that it will use to keep a session between the client and the Web Applicatio
    • <META> tag:
      • <META> tag also is considered a code injection attack, however, different from the XSS attack where undesirable scripts can be disabled, or the execution can be denied. The attack using this method becomes much more efficient because it's impossible to disable the processing of these tags in the browsers.
After describing the Session Fixation attack I will explain the attack scenario described in the picture using new chain of vulnerabilities (e.g. Session Fixation -> CSRF). An attacker sends an e-mail to an Html enabled e-mail client that contains some sample images uploaded to a malicious server, along with the malicious URL that performs the CSRF function and this time is bind to the fixed session (by using one or more of the techniques described above), waits until the user opens the e-mail and downloads the images or sets his/her e-mail to receive a notification when the victim user reads his/her e-mail. Thens he/she waits the logs of the malicious image server to be updated or waits to receive a read e-mail receipt in his/her mailbox. After the image is downloaded (and he/she sees that from e.g. /www/var/apache.logs etc) or the read receipt is received he/she will try to verify that the malicious function was executed.

The link with the fixated token will produce a GET Http request that looks like this:

GET /homepage/transferEuros=3000?maliciousUserAccount=9832487 HTTP/1.1
Host: victim.com
Keep-Alive: timeout=15
Connection: Keep-Alive
Cookie: Fixated Session

Note1: Obviously a Session Fixation attack can have devastating results even without the use of CSRF flaw. What I am saying here is that a Session Fixation combined with a CSRF attack amplifies the attack (e.g. the attacker will optimize his/her time attack frame by exploiting a chain of vulnerabilities rather than a single vulnerability).

Note2: Similar exploitation scenarios you can have when the web application does not provide the user with an authentication mechanism e.g. open registration forms used for submitting credit card details.

CSRF and bad architecture design

Although this category might not be exactly a CSRF issue, it is still very similar to a CSRF attack. This type of attack refers to the occasions were no proper random values are generated (based on user credentials) or values that are generated but do not have a session like behavior e.g. lack of authorization,  none random CAPTCHA, lack of entity authentication etc. By integrating this type of behavior to your application you endanger the application to became victim to multiple type of attacks.   

CSRF and Clickjaking

Clickjacking, also known as a "UI redress attack", happens is when an attacker uses multiple transparent or opaque layers to trick a user into clicking on a button or link on another page when they were intending to click on the the top level page. Thus, the attacker is "hijacking" clicks meant for their page and routing them to other another page, most likely owned by another application, domain, or both. Using a similar technique, keystrokes can also be hijacked. With a carefully crafted combination of stylesheets, iframes, and text boxes, a user can be led to believe they are typing in the password to their email or bank account, but are instead typing into an invisible frame controlled by the attacker.

For example, imagine an attacker who builds a web site that has a button on it that says "click here for a free iPod". However, on top of that web page, the attacker has loaded an iframe with your vulnerable e-banking account, and lined up exactly the "transfer money" button directly on top of the "free iPod" button. The victim tries to click on the "free iPod" button but instead actually clicked on the invisible "transfer money" button. In essence, the attacker has "hijacked" the user's click, hence the name "Clickjacking". Again the attack scenario would be the similar to the ones just described above so there is no need for me to modify and explain again the attack scenarion. What is interesting though would be to show you an iframe that performs a CSRF attack.

Well an iframe that performs a CSRF attack would look something like that:

<iframe src="http://www.victim.com/homepage/transferEuros=3000?maliciousUserAccount=9832487">

Note: You can see how beautiful this attack is and how simple and smooth can be implemented.

CSRF and Exposed Session Variables

By simply passing the session or other session variables in the URL e.g. such the AntiCSRF token, means asking for trouble. The Session Tokens (Cookie, SessionID, Hidden Field), if exposed, will usually enable an attacker to impersonate a victim and access the application illegitimately. As such, it is important that they are protected from eavesdropping at all times – particularly whilst in transit between the Client browser and the application servers.

The information here relates to how transport security applies to the transfer of sensitive Session ID data rather than data in general, and may be stricter than the caching and transport policies applied to the data served by the site. Using a personal proxy, it is possible to ascertain the following about each request and response:
  • Protocol used (e.g., HTTP vs. HTTPS)
  • HTTP Headers
  • Message Body (e.g., POST or page content)
Each time Session ID data is passed between the client and the server, the protocol, cache, and privacy directives and body should be examined. Transport security here refers to Session IDs passed in GET or POST requests, message bodies, or other means over valid HTTP requests. As you already understand stealing the Session ID and/or the AntiCSRF token might result in the attacker being able to form links such as the following one:

http://www.vulnerable.com/?sessionid=ligdlgkjdng?anticsrftoken=kjnsdldfksjdnk?transferEuros=3000?maliciousUserAccount=9832487   

Note: The above information can be used to generate a link for a malicious user.

The attack scenario?

For my demo I choose multidae vulnerable web application which can be found on OWASP's Vulnerable Apps VM, an intercepting proxy tool (I used Portswigger's Burp Proxy, however it is not essential, just a "View Source" from any browser can work on most cases) and an Apache web server.

In the following picture you can see the main page of Multidae's web application as it can be browsed by any -non authenticated- user.




In this web application any user can register an account, but our goal is to register the account with the administrator's privileges. Below is the "register user" page that any, unauthenticated user can see.




If we view the source of the "Register Account" page, we can identify the forms (and therefore the POST request) that are being sent to the web application. That data are then processed by the application and the user is created.


Now, the attacker can create his own form at his web server and populate the HTML fields with the data of the user he wants to create on the system. (Note: no code expertise is needed in order to create this HTML page!). The following picture, you can see the HTML page that creates on his web server. He creates a user named "andrew", with password "qwerty".


Now he launches the web server (192.168.200.14) hosting this page. At this point, he needs the user's interaction. This could be accomplished, for example, by a phishing attack scenario: the victim receives an email inviting the victim to visit the attacker's page saying "click here to win an iPhone 5", or he could attach this message this "iPhone 5 message" at the page he created!

Just imagine:



And this is how it will appear on the victim's web browser:


The victim, which is at the same time logged in with this account at Multidae web application, is now tricked to click on the button and submit a register user form with the username and password set by the attacker.

 Now user "andrew" can log in with the password set during the CSRF request.


At point the CSRF attack scenario is completed. We sucessfuly managed to exploit a CSRF vulnerability and add a user to the vulnerable web application.

The CASE studies for CSRF

This site here contains many popular web sites that were vulnerable to CSRF attacks. An interesting extract from the article can be found here:

"1. ING Direct (ingdirect.com)
Status: Fixed
We found a vulnerability on ING’s website that allowed additional accounts to be created on behalf of an arbitrary user. We were also able to transfer funds out of users’ bank accounts. We believe this is the first CSRF vulnerability to allow the transfer of funds from a financial institution. Specific details are described in our paper.
2. YouTube (youtube.com)
Status: Fixed
We discovered CSRF vulnerabilities in nearly every action a user could perform on YouTube. An attacker could have added videos to a user’s "Favorites," added himself to a user’s "Friend" or "Family" list, sent arbitrary messages on the user’s behalf, flagged videos as inappropriate, automatically shared a video with a user’s contacts, subscribed a user to a "channel" (a set of videos published by one person or group) and added videos to a user’s "QuickList" (a list of videos a user intends to watch at a later point). Specific details are described in our paper.
3. MetaFilter (metafilter.com)
Status: Fixed
A vulnerability existed on Metafilter that allowed an attacker to take control of a user’s account. A forged request could be used to set a user’s email address to the attacker’s address. A second forged request could then be used to activate the "Forgot Password" action, which would send the user’s password to the attacker’s email address. Specific details are described in our paper.
(MetaFilter fixed this vulnerability in less than two days. We appreciate the fact that MetaFilter contacted us to let us know the problem had been fixed.)
4. The New York Times (nytimes.com)
Status: Not Fixed. We contacted the New York Times in September, 2007. As of September 24, 2008, this vulnerability still exists. This problem has been fixed."

Note: You can see from the above extract that CSRF issues are very popular these days.

Tools for CSRFing the Web

The Burp Proxy tool (the Pro version of course) can be used to generate a proof-of-concept (PoC) cross-site request forgery (CSRF) attack for a given request.To access this function, select a URL or HTTP request anywhere within Burp, and choose "Generate CSRF PoC" within "Engagement tools" in the context menu.

When you execute this function, Burp shows the full request you selected in the top panel, and the generated CSRF HTML in the lower panel. The HTML uses a form with a suitable action URL, encoding type and parameters, to generate the required request when the browser submits the form.You can edit the request manually, and click the "Regenerate" button to regenerate the CSRF HTML based on the updated request.

You can test the effectiveness of the generated PoC in your browser, using the "Test in browser" button. When you select this option, Burp gives you a unique URL that you can paste into your browser (configured to use the current instance of Burp as its proxy). The resulting browser request is served by Burp with the currently displayed HTML, and you can then determine whether the PoC is effective by monitoring the resulting request(s) that are made through the Proxy.Some points should be noted regarding form encoding:

    •    Some requests (e.g. those containing raw XML or JSON) have bodies that can only be generated using a form with plain text encoding. With each type of form submission using the POST method, the browser will include a Content-Type header indicating the encoding type of the form that generated the request. In some cases, although the message body exactly matches that required for the attack request, the application may reject the request due to an unexpected Content-Type header. Such CSRF-like conditions might not be practically exploitable. Burp will display a warning in the CSRF PoC generator if this is liable to occur.

    •    If you manually select a form encoding type that cannot be used to produce the required request, Burp will generate a best effort at a PoC and will display a warning.

    •    If the CSRF PoC generator is using plain text encoding, then the request body must contain an equals character in order for Burp to generate an HTML form which results in that exact body. If the original request does not contain an equals character, then you may be able to introduce one into a suitable position in the request, without affecting the server's processing of it.

CSRF PoC Options

The following options are available:

    •    Include auto-submit script - Using this option causes Burp to include a small script in the HTML that causes a JavaScript-enabled browser to automatically submit the form (causing the CSRF request) when the page is loaded.

    •    Form encoding - This option lets you specify the type of encoding to use in the form that generates the CSRF request. The "Auto" option is generally preferred, and causes Burp to select the most appropriate encoding capable of generating the required request. 

The following picture shows a screen shot from Burp CSRF PoC tool while doing right click on an intercepted request:


The following picture shows the generated CSRF PoC:


Note: Right click the intercepted Http GET or POST request and click CSRF PoC. It should not be a problem if the web application accepts POST to GET interchanges for obvious reasons.


Prevention Measures That Do NOT Work

Using a Secret Cookie:

Remember that all cookies, even the secret ones, will be submitted with every request. All authentication tokens will be submitted regardless of whether or not the end-user was tricked into submitting the request. Furthermore, session identifiers are simply used by the application container to associate the request with a specific session object. The session identifier does not verify that the end-user intended to submit the request.

Only Accepting POST Requests:

Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed. Unfortunately, this logic is incorrect. There are numerous methods in which an attacker can trick a victim into submitting a forged POST request, such as a simple form hosted in an attacker's Website with hidden values. This form can be triggered automatically by JavaScript or can be triggered by the victim who thinks the form will do something else.

Multi-Step Transactions:

Multi-Step transactions are not an adequate prevention of CSRF. As long as an attacker can predict or deduce each step of the completed transaction, then CSRF is possible.

URL Rewriting:


This might be seen as a useful CSRF prevention technique as the attacker can not guess the victim's session ID. However, the user’s credential is exposed over the URL.

CSRF countermeasures 

CSRF attacks are very hard to trace and probably are not traceable unless one the two or more of the following conditions are met:
  1. Detailed Web Application user auditing exists and is enabled.
  2. Concurrent logins are not allowed (allowing concurrent logins would remove none repudiation).
  3. The Web Application binds the Web Application session with the user IP (that way if the user is behind a NAT only users from the same intranet would be able to perform a CSRF attack).
  4. AntiCSRF tokens are used per Web Application function. An AntiCSRF token in order to be effective would have to be:
    • Truly Random.
    • Bind to every Web Application function (different per Web Application function).
    • Behave like a session (e.g. expire after a certain time, expire e.t.c).
    • Use a two factor authentication per token (e.g make of a RSA token to generate the AntiCSRF to perform a transaction etc).
Other technologies for protecting against CSRF

In the web there are numerous references regarding the implementation of anti-CSRF tokens. Some examples can be found here: 
The mentality promoted by the above technologies is abvious, we should deploy a mechanism that would make unique every session initiated by the user. This can be achieved by sending the browser an anti-CSRF token that would be appended in every request the browser sends to the server. The above technique is being explained in more technical terms in OWASP's CSRF Prevention cheat sheet:

"These challenge tokens are the inserted within the HTML forms and links associated with sensitive server-side operations. When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token. By including a challenge token with each request, the developer has a strong control to verify that the user actually intended to submit the desired requests. Inclusion of a required security token in HTTP requests associated with sensitive business functions helps mitigate CSRF attacks as successful exploitation assumes the attacker knows the randomly generated token for the target victim's session. This is analogous to the attacker being able to guess the target victim's session identifier."

Epilogue

This blog post attempted to cover thoroughly the subject of CSRF and I believe that I managed to do that. Now there are obviously a lot more things to say about how to protect against a CSRF but for the purposes of this post is out of scope. Merry Christmas and a Happy New year.

References:
  1. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
  2. http://en.wikipedia.org/wiki/Cross-site_request_forgery
  3. https://www.owasp.org/index.php/Testing_for_Exposed_Session_Variables_(OWASP-SM-004)
  4. http://haacked.com/archive/2009/04/02/anatomy-of-csrf-attack.aspx
  5. https://www.owasp.org/index.php/Session_fixation
  6. http://ajaxian.com/archives/gmail-csrf-security-flaw
  7. http://www.portswigger.net/burp/help/suite_functions_csrfpoc.html
  8. https://nealpoole.com/blog/2012/03/csrf-clickjacking-and-the-role-of-x-frame-options/
  9. http://fragilesecurity.blogspot.gr/2012/11/cross-site-request-forgery-legitimazing.html
  10. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
  11. https://blogs.apache.org/infra/entry/apache_org_04_09_2010
  12. https://freedom-to-tinker.com/blog/wzeller/popular-websites-vulnerable-cross-site-request-forgery-attacks/
  13. https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Viewstate_.28ASP.NET.29

06/11/2012

The Da Vinci Cod(e) Review

Introduction

This article is about doing Web Application security code review properly. Or at least the way I do it, which after enough pentests and code audits I'm fairly confident counts as properly. The best setup for a review is having the running application and the source sitting in front of you at the same time. You spot something suspicious in the code, you pop over to the browser and confirm it fires. No guessing, no theoretical findings that quietly die in triage six months later.

Ideally this lives inside a CI/CD pipeline. Your SAST tool flags something on a commit, you spin up the branch in a local or staging instance, and you check whether the finding is actually reachable before anyone burns a sprint on it. Tool flags it, human proves it. That loop is where the real security value sits. Everything else is theatre.


But first, what actually is a security code review? It's a systematic pass through source code aimed at finding and fixing the security mistakes that got missed during development. That's it. People run it in different shapes: pair programming, informal walkthroughs, formal inspections. Sometimes it's an internal security team, sometimes an outside contractor.

Bringing in an independent third party has real value beyond just extra eyes. Someone who joined at the tail end of development has no "emotional attachment to the code". They didn't fight for that architecture decision in a meeting six months ago. That distance is worth paying for.

In a modern DevSecOps setup, code review isn't a single event anymore. PR reviews, SAST scans firing on every commit, and periodic deep-dive manual audits all run at once. The real shift over the last few years is treating this as a living process, not a gate you pass through once and forget.

Types of code review

Code review practices generally split into three buckets: pair programming, formal review, and lightweight review. Formal review, the Fagan inspection style, is the heavyweight option: multiple participants, multiple phases, developers sitting round a table walking through printed code line by line. It's thorough, and there's decades of data showing formal inspections catch defects other methods miss. Lightweight review needs far less overhead and, done properly, can be just as effective.

Lightweight reviews are often conducted as part of the normal development process:
  1. Over-the-shoulder – One developer looks over the author's shoulder as the latter walks through the code.
  2. Email pass-around – Source code management system emails code to reviewers automatically after checkin is made.
  3. Pair Programming – Two authors develop code together at the same workstation, such is common in Extreme Programming.
  4. Tool-assisted code review – Authors and reviewers use specialized tools designed for peer code review (e.g. GitHub Pull Requests, GitLab Merge Requests, Gerrit).
A fourth category has emerged: AI-assisted code review. Tools like GitHub Copilot, Semgrep/Opengrep's assistant, and Snyk Code now give real-time security feedback straight in the IDE or the PR. As of mid-2026, Copilot's code review can pull in agent skills and MCP servers, so it checks your PR against your own team's internal standards and tooling instead of a generic ruleset. That's a genuine capability jump. It's also, as I'll get to further down, a new place for things to go wrong. Same rule as ever: human verification is not optional.

Important note: Tools can be used to perform this task but they always need human verification. Tools do not understand context, which is the keystone of security code review. Tools are good at assessing large amounts of code and pointing out possible issues, but a person needs to verify every single result to determine if it is a real issue, if it is actually exploitable, and calculate the risk to the enterprise. This matters more now that so much of the code hitting your PRs was written by an LLM. Veracode's Spring 2026 GenAI code security study tested over 100 models and found 45% of AI-generated samples introduced an OWASP Top 10 vulnerability. AppSec Santa's 2026 run came out lower at 25.7% across 522 samples, still not a number you want anywhere near a production deploy. CodeRabbit's research put AI-written code at 1.88x more likely to carry a vulnerability than the human-written equivalent. And the velocity problem compounds it: AI-assisted developers ship commits three to four times faster than their peers but introduce security findings at roughly ten times the rate. Your SAST tool will flag a chunk of that. Only a human reviewer, one who understands the business context, decides whether the flagged pattern is actually exploitable or just noise.

What is the most important thing in a code review

The single most important thing you bring to a code review is a threat model. Threat modeling is a structured way of analysing an application's security: what you're protecting, who's coming after it, and how. It isn't a review technique on its own. It's the lens you review through, and doing it early in the SDLC means security gets built in from day one instead of bolted on afterwards. It also hands the reviewer a map: where the entry points sit, and what's actually at risk behind each one.

In 2020, a group of threat modeling practitioners, researchers and authors published the Threat Modeling Manifesto, a document that distills the collective knowledge of the community into values and principles, similar to the Agile Manifesto. The Manifesto anchors all threat modeling around four fundamental questions:
  1. What are we building? Understand the system through diagrams (DFDs, architecture diagrams).
  2. What can go wrong? Identify threats using frameworks like STRIDE, PASTA, LINDDUN, or Attack Trees.
  3. What are we going to do about it? Define countermeasures and mitigations.
  4. Did we do a good enough job? Validate and iterate on the threat model.
These four questions are your north star, whichever specific framework you end up reaching for. The mindset shift underneath all of it: look at the system the way an attacker would, not the way you built it. Threat modeling isn't a security-team-only exercise anymore either. It needs developers, architects, business analysts, DevOps, and security in the same room, or at least the same thread.

Threat Modeling Frameworks: A Modern Overview

There are several established frameworks. Which one you reach for depends on your organisation's maturity, what kind of system you're analysing, and whether you're chasing security risk, privacy risk, or business risk. Here's where things actually stand in 2026.

STRIDE

STRIDE is the most widely used framework, developed originally at Microsoft. It splits threats into six categories:
  • Spoofing: Can an attacker impersonate another user or system?
  • Tampering: Can an attacker modify data in transit or at rest?
  • Repudiation: Can an attacker deny having performed an action?
  • Information Disclosure: Can sensitive data leak to unauthorized parties?
  • Denial of Service: Can an attacker degrade or disrupt service availability?
  • Elevation of Privilege: Can an attacker gain unauthorized access to higher-level functions?
STRIDE suits teams new to threat modeling. It's quick to teach and quick to adopt, and it slots into agile sprints without much friction. In practice: draw a Data Flow Diagram of your system, then for every element ask "can this be spoofed? Tampered with?" and work down the six. Microsoft built STRIDE into their Security Development Lifecycle and credits it as one of the reasons their products got measurably more secure over the years that followed.

Limitation: STRIDE only covers security threats. It says nothing about privacy, doesn't connect to business risk, and doesn't account for attacker motivation. It's also static, built for design time, and won't adapt on its own as new threat intelligence comes in.

PASTA (Process for Attack Simulation and Threat Analysis)

PASTA is a seven-stage, risk-centric methodology from Tony UcedaVélez and Marco M. Morana. Where STRIDE sorts threats into categories, PASTA ties technical risk directly to business impact, which is why it shows up more often in regulated enterprises where every security decision needs a business justification attached.

The seven stages of PASTA are:
  1. Define Objectives: Identify business objectives, security requirements, compliance requirements, and data classification for the application in scope.
  2. Define Technical Scope: Map all system components, their relationships, interdependencies, and the attack surface.
  3. Application Decomposition: Break down the system into data flows, processes, trust boundaries, user roles, and permissions.
  4. Threat Analysis: Identify threat actors, their motivations, and create Attack Trees to model how they could achieve their goals.
  5. Vulnerability Analysis: Correlate threats with known vulnerabilities using data from vulnerability scanners, penetration test reports, and threat intelligence feeds.
  6. Attack Modeling: Simulate attack scenarios to test the viability of identified threats against existing countermeasures.
  7. Risk and Impact Analysis: Calculate residual risk, prioritize findings by business impact, and define remediation strategies.
PASTA fits mature organisations that want their security work tied to business risk, not floating on its own. It's the right depth for high-assurance systems: finance, healthcare, critical infrastructure. Its real edge over STRIDE is that it forces the room to be cross-functional: developers, architects, business analysts, risk professionals, and SOC team members all in the process together, not just the dev team ticking a security box.

Limitation: PASTA takes more expertise to run and a lot more time. It lives or dies on how good your data about the system and its architecture actually is. Don't treat it as a quick start. Budget for stakeholder coordination and expect weeks, not an afternoon.

Attack Trees

Attack Trees pair with any of the frameworks above. Bruce Schneier formalised them in 1999, building on earlier work by Edward Amoroso and the NSA, and they give you a visual, hierarchical map of how an attacker reaches a goal.

The structure is simple:
  • The root node represents the attacker's goal (e.g., "Steal user credentials").
  • Child nodes represent the different ways to achieve that goal.
  • Nodes are connected using AND/OR logic: OR nodes represent alternatives (any one path suffices), AND nodes represent steps that must all be completed.
  • Each node can carry additional metadata: likelihood, cost, required skill level, detectability.
For example, an Attack Tree for "Bypass Authentication" might look like:

Bypass Authentication [ROOT - OR]
├── Brute Force Password [OR]
│   ├── Online brute force (if no rate limiting)
│   └── Offline brute force (if password hashes leaked)
├── Credential Stuffing [OR]
│   └── Use credentials from previous breaches
├── Session Hijacking [OR]
│   ├── Steal session cookie via XSS
│   └── Session fixation attack
├── Exploit Password Reset [OR]
│   ├── Predictable reset tokens
│   └── Account takeover via email compromise
└── SQL Injection on Login [OR]
    └── Bypass authentication via tautology (e.g. ' OR '1'='1)

Attack Trees earn their keep past the diagram itself: they hand you tactical, targeted defenses instead of a vague "we should improve auth." They also work well in front of leadership. Non-technical stakeholders can follow a tree even if they can't follow a CVSS score. Inside PASTA specifically, you build Attack Trees during stage four, Threat Analysis, to model how each identified threat actor gets to their goal.

Tip: Tools like OWASP Threat Dragon, Microsoft Threat Modeling Tool, IriusRisk, and Devici can help you build and maintain Attack Trees as living documents that evolve with your application.

LINDDUN (Privacy Threat Modeling)

LINDDUN comes out of KU Leuven and covers what STRIDE doesn't: privacy. STRIDE handles confidentiality, integrity, availability. LINDDUN handles the privacy-specific harms those categories were never built to catch. With GDPR, CCPA, and HIPAA enforcement only getting stricter, skipping privacy threat modeling on anything that touches personal data is a bet I wouldn't take.

LINDDUN stands for:
  • Linking: Can an adversary combine data to learn more about an individual?
  • Identifying: Can the identity of a data subject be determined?
  • Non-repudiation: Can a user be unable to deny an action (sometimes a privacy threat, not just a security feature)?
  • Detecting: Can an adversary detect that a user is using a system?
  • Data Disclosure: Can personal data leak to unauthorized parties?
  • Unawareness: Are users insufficiently informed about data collection and processing?
  • Non-compliance: Does the system fail to comply with privacy regulations and best practices?
LINDDUN runs on the same four Manifesto questions and can sit on the same DFD as STRIDE, so you're not duplicating the diagramming work to cover both security and privacy. It comes in a few flavours: LINDDUN GO (a card-based, gamified version for a fast brainstorm session), LINDDUN PRO (a systematic, exhaustive approach starting straight from the DFD), and LINDDUN MAESTRO (the advanced approach for enriched system descriptions).

When to use it: If your application processes personal data (user profiles, health records, financial information, location data), run LINDDUN alongside STRIDE. Regulatory fines plus the reputational hit from a privacy incident now regularly outstrip what a plain security breach costs you.

Choosing Your Framework

You don't have to marry one framework. Most teams start with STRIDE for general coverage, layer in LINDDUN once personal data enters the picture, and bring in PASTA later once the organisation wants threats tied to business objectives instead of just a list of findings. Attack Trees slot into any of them when you need to drill into one specific scenario. The programs that actually work evolve this way: lightweight first, cross-functional later. Nobody builds PASTA on day one.

The Threat Modeling Process

Regardless of which framework you choose, the threat modeling process can be decomposed into 3 high level steps:

Step 1: Decompose the Application:
  • Create use-cases to understand how the application is used.
  • Identify entry points (APIs, web forms, file uploads, message queues, webhooks).
  • Identify assets (databases, secrets, PII, session tokens, cryptographic keys).
  • Identify trust levels and trust boundaries between external entities.
  • Map data flows using DFDs or sequence diagrams.
Note: This stage is about understanding the context of the Web Application and everything touching it. In a modern architecture, that means microservices communication, API gateways, third-party integrations, cloud provider boundaries, and the container orchestration layer sitting under all of it.

The following images show the Business Architecture (Business Owner's Perspective) and Business Architecture Behavior of a Web Application:


Note: Lists the entities important to the business. Business entities can be a person, a thing or a concept that is part of or interacts with the business process (Proforma 2003). In the example of "XYZ-Match", the business entities include the following: Investors, Entrepreneurs, "XYZ-Match" web system.


Note: Lists the processes in which the business operates. In the example of "XYZ-Match", "Investor listing information to Venture Capital Directory" is one of such business processes.

Step 2: Determine and rank threats using your chosen categorization methodology:
  • Authentication and Identity Management
  • Authorization and Access Control
  • Session Management
  • Input Validation and Output Encoding
  • Data Protection in Storage and Transit (encryption at rest, TLS, key management)
  • Auditing, Logging, and Monitoring
  • Configuration Management and Secrets Management
  • Error Handling and Exception Management
  • Supply Chain and Dependency Security
Note: This stage is about mapping vulnerabilities to a category. Threat listing is an important part of a Web Application code audit. Threat lists based on the STRIDE model are useful for identifying threats against attacker goals. Grouping the Web Application threats this way tells you where the actual weak points cluster. If half your findings land under Authentication, that's your blinking red light: not six unrelated bugs, one systemic gap wearing six different masks.

Step 3: Determine countermeasures and mitigation.

Note: Such countermeasures can be identified using threat-countermeasure mapping lists. The risk mitigation strategy might involve evaluating these threats from the business impact that they pose and reducing the risk.

The objective of risk management should be to reduce the impact that the exploitation of a threat can have to the application (not to necessarily mitigate the risk!). This can be done by responding to a threat with a risk mitigation strategy. In general there are five options to mitigate threats:
  1. Do nothing: for example, hoping for the best.
  2. Informing about the risk: for example, warning user population about the risk.
  3. Mitigate the risk: for example, by putting countermeasures in place.
  4. Accept the risk: for example, after evaluating the impact of the exploitation (business impact).
  5. Transfer the risk: for example, through contractual agreements and insurance.
The decision of which strategy is most appropriate depends on the impact an exploitation of a threat can have, the likelihood of its occurrence, and the costs for transferring or avoiding it.

  • Define the application requirements:
  1. Identify business objectives
  2. Identify user roles that will interact with the application
  3. Identify the data the application will manipulate
  4. Identify the use cases for operating on that data that the application will facilitate
  • Model the application architecture:
    • Model the components of the application
    • Model the service roles that the components will act under
    • Model any external dependencies (third-party APIs, open-source libraries, cloud services)
    • Model the calls from roles, to components and eventually to the data store for each use case
  • Identify any threats to the confidentiality, availability and integrity of the data and the application based on the data access control matrix that your application should be enforcing
  • Assign risk values and determine the risk responses
  • Determine the countermeasures to implement based on your chosen risk responses
  • Continually update the threat model based on the emerging security landscape. Threat modeling is not a one-time activity, it must evolve as the application, its dependencies, and the threat landscape change.

Modern Tools for Security Code Auditing

The tooling has moved a long way past grep. Graudit, RATS, and findstr, the old signature scanners, still have some educational value if you want to understand pattern matching at its most basic. But production SAST today does semantic analysis, not string matching. Here's where the field actually sits.

Semgrep / Opengrep

Semgrep is a lightweight static analysis tool built on semantic pattern matching rather than plain text matching. It understands code structure, so it stays fast without falling back to regex guesswork, and you write custom rules in YAML that look almost like the code you're hunting for.

semgrep scan --config=auto /path/to/code

It's fast, needs no compilation step, covers 20+ languages, and drops straight into CI/CD, IDE plugins, and PR checks. The commercial Semgrep AppSec Platform layers on cross-file/cross-function dataflow analysis, SCA, secrets detection, and an AI-powered assistant for triage and autofix.

Note: Here's the part that's actually changed since I last touched this piece. In January 2025, Semgrep shifted its open-source licensing, and ten-plus rival AppSec vendors (Aikido, Endor Labs, Arnica, Kodem, Legit, Mobb, Orca Security, Phoenix Security and others) forked the community edition into Opengrep under LGPL-2.1. By mid-2026 that fork is not a scrappy side project: 189+ contributors, 9,500+ commits, a full-time OCaml team on the core engine, and releases shipping on a roughly weekly cadence (v1.20 added Python structural pattern matching in April, v1.21 exposed taint-intrafile over LSP for IDE integrations in May). It restores taint analysis, inter-procedural scanning, and Windows support, all of which the Semgrep Community Edition had dropped, and it kept the original rule format and SARIF output, so swapping the binary into an existing pipeline is close to a non-event. If you're choosing between the two today, Opengrep is the one with no licensing string attached.

CodeQL (GitHub Advanced Security)

CodeQL compiles your source into a queryable relational database: the AST, the data flow graph, the control flow graph. You write queries in QL, a Datalog-derived declarative language, to traverse it. It's the deep-end tool. CodeQL variant analysis has turned up more than 400 CVEs in open-source projects to date, and it stays free for open-source repos.

codeql database create mydb --language=java --source-root=/path/to/code
codeql database analyze mydb codeql/java-queries:codeql-suites/java-security-and-quality.qls --format=sarif-latest --output=results.sarif

Copilot Autofix now sits on top of CodeQL results and suggests AI-generated fixes directly in the PR. Genuinely useful when the fix is mechanical, genuinely dangerous when it isn't and nobody checks.

Limitation: QL has a real learning curve, and building the database means compiling your code first, so it's slower than Semgrep for a quick pass. Treat this as a research and deep-audit tool, not something you bolt onto a fast-moving DevSecOps pipeline as your only gate.

Other Notable Tools

  • Snyk Code: Developer-focused SAST with real-time IDE scanning and AI-trained detection engine. Strong on AI-generated code pattern detection.
  • SonarQube: Combines SAST with code quality checks. Good for teams that want security and maintainability in one platform.
  • Checkmarx / Veracode / OpenText (Fortify): Enterprise-grade SAST platforms with deep scanning, compliance reporting, and legacy language support.
  • Bandit: Open-source Python-specific SAST tool. Lightweight and great for Python-heavy shops.
  • OWASP Dependency-Check / Trivy: SCA tools for scanning third-party dependencies for known vulnerabilities.
  • GitGuardian / Gitleaks: Secrets detection tools that scan repos for exposed credentials, API keys, and tokens.

Important: No single tool covers everything, and anyone selling you one that does is selling. A real AppSec stack layers SAST, SCA, secrets detection, DAST, and IaC scanning, each one catching what the others miss. And the golden rule hasn't moved an inch: a tool is only as good as the human reviewing its output.

The new attack surface: AI agents in the review loop

There's a wrinkle in all of this that didn't exist when I first wrote this piece: the reviewer itself might now be an agent with tool access, not just a human with a linter.

GitHub made Copilot code review's agent skills and MCP server support generally available in July 2026, across Pro, Pro+, Business, and Enterprise. Your review agent can now pull in your team's internal tools and standards mid-review, which is a real capability jump. It also means your review agent has become a thing an attacker can target, not just a thing they hide from.

Case in point: in July 2026, researchers disclosed a flaw in Microsoft's own Azure DevOps MCP server where a single invisible comment on a pull request could hijack the reviewer's AI coding agent. The server tool returning PR descriptions didn't guard against prompt injection, so text a human reviewer would never even notice could redirect the agent's actions. And in April 2026, OX Security disclosed a systemic MCP architecture flaw across a supply chain touching over 150 million package downloads, roughly 200,000 vulnerable instances by their estimate. The original MCP spec shipped without mandatory authentication and assumed servers and their tools were inherently trustworthy. Attackers noticed that assumption immediately.

Run this through STRIDE for two minutes and it's obvious why this matters: an MCP-connected review agent is a new entry point with elevated privilege (it can comment, approve, sometimes merge) and a new spoofing surface (anything that looks like PR content but is actually an instruction). Threat model your review tooling the same way you threat model the application it's reviewing. If your AI code review agent has MCP tool access, that access itself needs a security review before it goes anywhere near production PRs. Don't skip that step because the tool is "just for code review." That's exactly the reasoning that got the Azure DevOps server compromised.

Cod(e) reviewing for SQL Injection

SQL Injection is still sitting in the OWASP Top 10 after multiple revisions, which after this many years should embarrass the industry more than it does. It persists because of one specific, boring mistake that keeps recurring: constructing SQL queries by concatenating untrusted input into a string.

Use parameterized queries (PreparedStatements in Java) instead of dynamic SQL statements. Validate all external input: ensure that all SQL statements recognize user inputs as variables, and that statements are precompiled before the actual inputs are substituted for the variables. Think about SQL injection defense in layers across the whole Web Application system. Input validation should occur at the Web Application input filter, the framework/ORM layer, and the database layer itself. Additional layers of defense can be added through a Web Application Firewall (WAF) and a Database Activity Monitor. Neither is a substitute for fixing the query.

The following picture shows a sequence of yes and no flow chart explaining an SQL injection flow:


Note: This is a simplified SQL Injection threat model. In practice, the decision tree branches further when you consider second-order injection, blind SQLi, and out-of-band channels.

The Vulnerable Code (Java: what NOT to do)

// VULNERABLE: SQL Injection via string concatenation
// This is the classic mistake: user input directly embedded in SQL

String username = request.getParameter("USER");       // From HTTP request, UNTRUSTED
String password = request.getParameter("PASSWORD");   // From HTTP request, UNTRUSTED

// DANGER: Direct concatenation of user input into SQL query
String sql = "SELECT User_id, Username FROM USERS WHERE Username = '"
    + username + "' AND Password = '" + password + "'";

Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);

// An attacker entering: Username = ' OR '1'='1' --
// Produces: SELECT User_id, Username FROM USERS
//           WHERE Username = '' OR '1'='1' --' AND Password = ''
// Result: Authentication bypass, returns all users

When SQL statements are dynamically created as software executes, the input data can truncate, malform, or expand the query you meant to run. request.getParameter() here pulls straight from the HTTP request with zero validation: no length check, no character allowlist, nothing. That gap is exactly what lets an attacker submit SQL as the payload and rewrite what the statement actually does.

The Secure Code (Java: PreparedStatement / Parameterized Query)

// SECURE: Parameterized query using PreparedStatement
// The SQL structure is precompiled; user input is ALWAYS treated as data

String username = request.getParameter("USER");
String password = request.getParameter("PASSWORD");

// The '?' placeholders ensure input can never alter the query structure
String sql = "SELECT User_id, Username FROM USERS WHERE Username = ? AND Password = ?";

try (PreparedStatement pstmt = connection.prepareStatement(sql)) {

    pstmt.setString(1, username);  // Bound as data, not SQL code
    pstmt.setString(2, password);  // Bound as data, not SQL code

    try (ResultSet rs = pstmt.executeQuery()) {
        if (rs.next()) {
            int userId = rs.getInt("User_id");
            String loggedUser = rs.getString("Username");
            // Authentication successful
        } else {
            // Authentication failed
        }
    }
} catch (SQLException e) {
    logger.error("Database error during authentication", e);
    // NEVER expose stack traces or SQL errors to the user
}

The PreparedStatement precompiles the query with placeholder markers (?). Call setString() and the JDBC driver treats the input strictly as a string literal, full stop. It can never be reinterpreted as SQL code. Feed it ' OR '1'='1 and the database goes looking for a username that is literally that string. It finds nothing, because nobody's username is ' OR '1'='1.

Modern Alternative: Using an ORM (JPA/Hibernate)

In modern Java applications, you often interact with the database through an ORM rather than raw JDBC. Here is how the same query looks using JPA (Java Persistence API):

// SECURE: JPA Named Query, parameterized by default

@Entity
@NamedQuery(
    name = "User.findByCredentials",
    query = "SELECT u FROM User u WHERE u.username = :username AND u.password = :password"
)
public class User { ... }

// Usage:
TypedQuery<User> query = entityManager.createNamedQuery("User.findByCredentials", User.class);
query.setParameter("username", request.getParameter("USER"));
query.setParameter("password", request.getParameter("PASSWORD"));
List<User> results = query.getResultList();

Warning: ORMs don't make you safe by default. Build your JPQL or HQL with string concatenation and you've recreated the exact same hole in a fancier wrapper. The rule doesn't change with the abstraction layer: always use parameterized queries.

Python Example (for comparison)

# VULNERABLE: string formatting with untrusted input
cursor.execute(f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'")

# SECURE: parameterized query
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))

What to grep for during code review (SQL Injection indicators)

When performing a manual code review or writing custom SAST rules, look for these patterns:
  • Statement.execute( or Statement.executeQuery( combined with string concatenation (+)
  • "SELECT ... " + variable or "INSERT ... " + variable or "UPDATE ... " + variable
  • String.format() used to build SQL queries
  • f"SELECT ..." (Python f-strings in SQL context)
  • cursor.execute("... %s ..." % variable) (Python old-style string formatting: not the same as a parameterized %s placeholder)
  • $"SELECT ..." (C# string interpolation in SQL context)
A Semgrep rule to detect Java SQL injection looks like this:

# semgrep-rule: java-sql-injection.yaml
rules:
  - id: java-sqli-string-concat
    patterns:
      - pattern: |
          String $QUERY = "..." + $INPUT + "...";
          ...
          $STMT.executeQuery($QUERY);
    message: >
      Potential SQL injection: user input concatenated into SQL query.
      Use PreparedStatement with parameterized queries instead.
    severity: ERROR
    languages: [java]

Epilogue

The actual goal of a security code review is teaching developers to write secure code in the first place. Everything else, the finding count, the severity ratings, the compliance checkbox, is secondary to that. Give developers a controlled set of rules to measure their own code against and you get better code next sprint, not just a patched bug this one. Semgrep, Opengrep, CodeQL, all of them work best when they deliver that feedback immediately: in the IDE, in the PR, while the context is still fresh in the developer's head.

The landscape has moved a long way since grep-based scanning. We've got AI-assisted remediation, cross-function taint analysis, reachability-based SCA, privacy-specific threat modeling, and now AI agents sitting inside the review pipeline itself with their own attack surface. None of that changes the fundamental truth: tools augment judgment, they don't replace it. The best reviews I've done, and the ones I've watched other people do well, always came down to a reviewer who knew the right tool for the job, checked every finding against real context, and could translate the risk into terms that got a business to actually act on it.

Threat model your applications. STRIDE for security, LINDDUN for privacy, PASTA when you need threats tied to business impact, Attack Trees when you need to drill into one specific scenario. Threat model your AI tooling too. It has entry points and trust boundaries just like everything else you're reviewing. Embed SAST in your pipeline. Review every finding with human eyes. And never, ever concatenate user input into a SQL query. Fifteen years into this industry and I'm still writing that sentence, which tells you everything about how well we're actually doing.

References:

03/11/2012

Crypto for pentesters


Introduction

The purpose of this paper is to emphasize in the importance of cryptography, focus in RSA asymmetric cryptographic algorithm and explain:

  • What is cryptography
  • Why cryptography is important
  • History of Cryptography
  • Mathematical RSA operations
  • How to perform an RSA brute-force

What is Cryptography

Cryptography (or cryptology; from Greek κρυπτός, kryptos, "hidden, secret"; and γράφω, gráphō, "I write", or -λογία, -logia, respectively) is the practice and study of hiding information. Modern cryptography intersects the disciplines of mathematics, computer science, and engineering. Applications of cryptography include ATM cards, computer passwords, and electronic commerce. [2]

Until recently cryptography referred mostly to encryption, which is the process of converting ordinary information (plaintext) into unintelligible gibberish (i.e. cipher-text). [4] Decryption is the reverse, in other words, moving from unreadable cipher-text back to plaintext. A cipher is a pair of algorithms that create the encryption and the reversing, also called decryption. [4] The operation of an algorithmic cipher is controlled by both the algorithm and in each instance by a key. The key is a secret parameter (ideally known only to the communicants) for a specific message exchange context. [4]

In order for two parties to exchange a cryptographic message both must have one or two secret keys (it depends if the parties use an asymmetric or a symmetric algorithm) and a known mathematical cryptographic algorithm (both parties must know the details of the cryptographic algorithm) the following diagram shows the process. 



Picture2: Simple encryption decryption operation (if the cryptography used is symmetric then key1=key2) [3]

Note: Secret keys are very important, as ciphers without variable size keys can be trivially broken with only the knowledge of the cipher used and are therefore not useful at all in most cases.

History of Cryptography

Before the modern era, cryptography was concerned solely with message confidentiality (i.e., encryption) — conversion of messages from a comprehensible form into an incomprehensible one and back again at the other end, rendering it unreadable by interceptors or eavesdroppers without secret knowledge (namely the key needed for decryption of that message). Encryption was used to (attempt to) ensure secrecy in communications, such as those of spies, military leaders, and diplomats. [6]

The earliest forms of secret writing required little more than local pen and paper analogy, as most people could not read. More literacy, or literate opponents, required actual cryptography. The main classical cipher types are transposition ciphers, which rearrange the order of letters in a message (e.g., 'hello world' becomes 'ehlol owrdl' in a trivially simple rearrangement scheme), and substitution ciphers, which systematically replace letters or groups of letters with other letters or groups of letters (e.g., 'fly at once' becomes 'gmz bu podf' by replacing each letter with the one following it in the Latin alphabet). [6]

Asymmetric and Symmetric Cryptography  

Cryptography consists from two main categories (some people might claim more categories but for the papooses of this paper two categories cover the needs of this paper). The fist category is symmetric cryptography and the second category is asymmetric cryptography.

Symmetric Cryptography

Symmetric Cryptography uses cryptographic algorithms that use identical cryptographic keys for both decryption and encryption (this is not entirely true, but again for the purposes of this paper we accept it as a fact).The Symmetric Cryptography keys, in practice, represent a shared secret between two or more parties that can be used to maintain a private information link. [5] The following simple mathematical relationships can describe the relation between decryption and encryption in Symmetric Cryptography.

Encryption ( k , Plaintext ) = Cipher (1) 

Decryption ( k , Cipher ) = Plaintext (2) 

Where k a secret shared value and Plaintext the data input we want to convert into cipher. From relationships (1) and (2) we can conclude that: 

Plaintext = Decryption ( k , Cipher ) = Decryption ( k , Encryption ( k , Plaintext )) (3) 

Note: Among the most popular and well-respected symmetric algorithms ARE Twofish, Serpent, AES (Rijndael), Blowfish, CAST5, RC4, TDES, and IDEA.





Picture3: Symmetric cryptography [7]

Asymmetric Cryptography


Asymmetric Cryptography also known as Public key cryptography is a cryptographic category which involves the use of asymmetric cryptographic key algorithms.The asymmetric key algorithms are used to create a mathematically related key pair: a secret private key and a published public key. [6]

The following simple mathematical relationships can describe the relation between decryption and encryption in Asymmetric Cryptography.

Encryption ( k1 , Plaintext ) =  Cipher (4)

Decryption ( k2 , Cipher ) =  Plaintext (5)

Where k2 a secret non shared value, k1 a non secret shared value and Plaintext the data input we want to convert into cipher. From relationships (4) and (5) we can conclude that:

Plaintext = Decryption ( k2 , Cipher ) = Decryption ( k2 , Encryption ( k1 , Plaintext )) (6)

In relationship we can realize that the decryption of the Plaintext is a more complex relationship that is dependents to both keys to be used.Public key cryptography is used widely. It is the approach which is employed by most cryptosystems. It underlies such Internet standards as Transport Layer Security (TLS), PGP, and GPG.The most famous asymmetric algorithm is RSA. In cryptography, RSA (which stands for Rivest, Shamir and Adleman who first publicly described it) is an algorithm for public-key cryptography. RSA is widely used in electronic commerce, and is believed to be secure when proper secret keys are used.






Picture4: Asymmetric cryptography [7]


Asymmetric and Symmetric Cryptography revised 

Unlike Symmetric Cryptography, Asymmetric Cryptography uses a different key for encryption than for decryption. I.e., a user knowing the encryption key of an asymmetric algorithm can encrypt messages, but cannot derive the decryption key and cannot decrypt messages encrypted with that key. This difference is the most obvious difference of Symmetric and Asymmetric Cryptography. Another difference of Symmetric and Asymmetric Cryptography is the mathematical properties of each type of algorithm and they way the mathematical algorithm is implemented in a hardware or software device (further explanation of these differences are out of the scope of this paper).

Why RSA is important

The RSA Cryptographic algorithm is being exploited by a company named also RSA. The company RSA is the security division of EMC (EMC acquired RSA for its security products in 2006). RSA Laboratories is the research center of RSA, The Security Division of EMC, and the security research group within the EMC Innovation Network. The group was established in 1991 at RSA Data Security, the company founded by the inventors of the RSA public-key cryptosystem. Through its applied research program and academic connections, RSA Laboratories provides state-of-the-art expertise in cryptography and data security for the benefit of RSA and EMC. [10]

Represented by the equation "c = me mod n," the RSA algorithm is widely considered the standard for encryption and the core technology that secures the vast majority of the e-business conducted on the Internet. The U.S. patent for the RSA algorithm (# 4,405,829, "Cryptographic Communications System And Method") was issued to the Massachusetts Institute of Technology (MIT) on September 20, 1983, licensed exclusively to RSA Security and expires on September 20, 2000. [9]

For nearly two decades, more than 800 companies spanning a range of global industries have turned to RSA Security as a trusted, strategic partner that can provide the proven, time-tested encryption implementations and resources designed to speed time to market. These companies, including nearly 200 so far in 2000, rely on RSA BSAFE® security software for its encryption implementation and value-added services for a broad range of B2B, B2C and wireless applications. [9]

Math’s behind RSA

The RSA algorithm involves the three following steps:
  1. Key generation.  
  2. Encryption. 
  3. Decryption.

Note: This is a simplistic approach of RSA.

RSA Key generation

RSA includes a public key and a private key. The public key can be known to everyone and is used for encrypting messages. Messages encrypted with the public key can only be decrypted using the private key. The keys are generated the following way:


1.     Choose two distinct prime numbers p and q. In mathematics, a prime number (or a prime) is a natural number that has exactly two distinct natural numbers 1 and itself. That means that a prime number can only be divided by 1 and itself: [13]

Example 1:  5/5 = 1

Example 2: 5/1 = 5

Very simplistically talking, it means that the remainder of the division of a prime number with any integer besides 1 and itself should be 0!!

Example 3: 5/2 = 2, 5 (2, 5 is not an integer)

The first fifteen prime numbers are:


Example 4: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47

Note: For security purposes, the integer’s p and q should be chosen uniformly at random and should be of similar bit-length. [8]



2.     Compute n = pq (a), where n is used as the modulus for both the public and private keys. For the purposes of this paper we will not use long secure integers. (as soon as we have the values n and φ, the values p and q will no longer be useful to us).

Note: For the algebra to work properly, these two primes must not be equal. To make the cipher strong, these prime numbers should be large, and they should be in the form of arbitrary precision integers with a size of at least 1024 bits (bits are used when cryptography is applied in real life examples).

Example 3:  (a) n = pq (b) which means that if p = 2 and q = 3 then n = 2*3 = 6 (both 2 and 3 are prime based in Example 4).



Now that we have the values n and φ, the values p and q will no longer be useful to us. However, we must ensure that nobody else will ever be able to discover these values. Destroy them, leaving no trace behind so that they cannot be used against us in the future. Otherwise, it will be very easy for an attacker to reconstruct our key pair and decipher our cipher text.

3.     Compute φ(pq) = (p − 1)(q − 1) (c) or φ(n) = (p − 1)(q − 1). (φ is Euler's totient function [11], Euler's totient function is out of the scope of this paper).

4.     Choose an integer e such that:

·      1 < e < φ (pq) or
·      1 < e < φ (n) or
·      1 < e < (p − 1) (q − 1) (d)

And e and φ (pq) have no common divisors other than 1. We randomly select a number e (the letter e is used because we will use this value during encryption) that is greater than 1, less than φ, and relatively prime to φ. Two numbers are said to be relatively prime if they have no prime factors in common. Note that e does not necessarily have to be prime.  

The value of e is used along with the value n to represent the public key used for encryption.

·      e is released as the public key exponent

5.     Determine d (using modular arithmetic) which satisfies the relation:




This is often computed using the extended Euclidean algorithm [12] (Euclidean algorithm is out of the scope of this paper).

·      d is kept as the private key exponent.

Note: To calculate the unique value d (to be used during decryption) that satisfies the requirement that, if d * e is divided by φ, then the remainder of the division is 1. The mathematical notation for this (as already described above) is d * e = 1(mod φ).

In mathematical jargon, we say that d is the multiplicative inverse of e modulo φ [15]. The value of d is to be kept secret. If you know the value of φ, the value of d can be easily obtained from e using a technique known as the Euclidean algorithm. If you know n (which is public), but not p or q (which have been destroyed), then the value of φ is very hard to determine. The secret value of d together with the value n represents the private key. The public key consists of the modulus n and the public (or encryption) exponent e. The private key consists of the modulus n and the private (or decryption) exponent d which must be kept secret.

RSA Encryption


RSA Cryptographic User A transmits his public key (n,e) to RSA Cryptographic User B and keeps his private key secret (d,e). RSA Cryptographic User B then wishes to send a secret integer m to RSA Cryptographic User A. He first turns m into an integer 0 < m < n by using an agreed-upon reversible procedure (only known to Users A and B). He then computes the cipher text c corresponding to: [9]




Note: And the encryption is successful. User A is the only person that can decrypt the secret integer m.  


RSA Decryption

RSA Cryptographic User A can recover m from c by using her private key exponent d by the following computation:





Note: Given m, he can recover the original message m by using the agreed-upon reversible procedure.


RSA Encryption/Decryption Simple example

For the purposes of this paper we are going to use a very simple number example. Based on Example 4 we have to:



1.     Choose q = 47 and q = 73. Based in mathematical relationship (b) is n = pq => n = 3431 also from relationship (c) we conclude that:

(c) =>  φ(pq) = (p − 1)(q − 1) or φ(n) = φ(pq) = φ(6) = (73-1)(47-1) = 72*46 = 3312 =>  φ = 3312


2.     Now that we have n and φ, we should discard p and q, and destroy any trace of their existence.

3.     Next, we randomly select a number e, that e > 1 and e is coprime [16] to 3312 (which is φ). We choose e = 425

4.     Then the modular inverse of e is calculated to be the following: d = 1769

5.     We now keep d private and make e and n public.

6.     Assume that we have plaintext data represented by the following simple number:

Plaintext = 707

7.     The encrypted data is computed by c = me (mod n) as follows:

Cipher text = 707^425(mod 3431) = 2142

8.     The cipher text value cannot be easily reverted back to the original plaintext without knowing d (or, equivalently, knowing the values of p and q). With larger bit sizes, this task grows exponentially in difficulty. If, however, you are privy to the secret information that d = 1769, then the plaintext is easily retrieved using     m = c d(mod n) as follows:

Plaintext = 2142^1769(mod 3431) = 707


Why RSA can’t break

The security of the RSA cryptosystem is based on two mathematical problems:

  1. The problem of factoring large numbers
  2. The RSA problem.
In number theory, integer factorization or prime factorization is the breaking down of a composite number into smaller non-trivial divisors, which when multiplied together equal the original integer. [17] In cryptography, the RSA problem summarizes the task of performing an RSA private-key operation given only the public key. [18] Full decryption of an RSA cipher text is thought to be infeasible on the assumption that both of these problems are hard because no efficient algorithm exists for solving them.


Appendix

C

Cryptography: Is the process of converting ordinary information (plaintext) into unintelligible gibberish.



Cipher: Is unintelligible gibberish



Coprime: In mathematics, two integers a and b are said to be coprime or relatively prime if they have no common positive factor other than 1 or, equivalently, if their greatest common divisor is 1. [16]

D



Decryption: Is the reverse process of encryption

M

Multiplicative inverse: In mathematics, a multiplicative inverse or reciprocal for a number x, denoted by 1⁄x or x −1, is a number which when multiplied by x yields the multiplicative identity, 1. [15]

P

Plaintext: Is ordinary readable information

Problem of factoring large numbers: In number theory, integer factorization or prime factorization is the breaking down of a composite number into smaller non-trivial divisors, which when multiplied together equal the original integer. [17]

Prime numbers: In mathematics, a prime number (or a prime) is a natural number that has exactly two distinct natural number divisors: 1 and itself. [13]


References

[2]: Liddell and Scott's Greek-English Lexicon. Oxford University Press. (1984)



NODE2Shell The CVE!!

// cve-2026-111497 // node.js // brotli // pre-auth rce TL;DR Node.js bundles Google's Brotli decoder. On the 22.x, 24.x and 26.x lines...