Table of contents
- Understanding Taint Analysis
- The Role of Sources and Sinks
- Why Taint Analysis is Important
- Finding Sources and Sinks in Different Languages and Frameworks
- JavaScript and Web Development sources
- TypeScript and React sources
- DOM-XSS sinks
- JavaScript Injection sinks
- Open-Redirection sinks
- Python and Django/Flask
- Java and Spring
- C# and ASP.NET
- Steps to Implement Taint Analysis
- Tools to Aid
- Conclusion
During testing or code reviews, it’s crucial to understand how users input flows through a system. The ability to read the code of the application and understand it thoroughly is just as important as breaking that application. This understanding enables us to spot weaknesses and safeguard the system more effectively. One powerful technique to achieve this is taint analysis. In that spirit, let's delve into the concepts of sources and sinks.
Understanding Taint Analysis
Taint analysis is a method used to track the flow of data through a program, start to end. It helps in identifying how data from an untrusted source can affect the execution of a program, potentially leading to security breaches.
The Role of Sources and Sinks
In taint analysis, the concepts of sources and sinks are fundamental:
-
Sources: These are points in the program where untrusted data enters. Examples include user input fields, network interfaces, and external databases.
Sinks: These are points where the data ends up or is executed. Sinks can include places where data is written to a file, displayed on the UI, or used in a database query.
Why Taint Analysis is Important
When we test systems or do code reviews, we don’t always have the luxury of a UI to observe how data flows. In such a scenario taint analysis is apt. It allows us to trace the path of user inputs through the system, highlighting how they interact with different components and where they ultimately end up. This visibility is critical in identifying potential vulnerabilities, such as SQL injection points, cross-site scripting (XSS) vulnerabilities, and other forms of data mishandling.
Finding Sources and Sinks in Different Languages and Frameworks
The methods for identifying sources and sinks can vary depending on the programming language and framework being used. Here’s a guide on how to approach this in some common scenarios:
JavaScript and Web Development sources
JavaScript sources include various properties and methods that can accept user input:
document.URL
: Returns the URL of the document.document.documentURI
: Returns the URI of the document.document.cookie
: Accesses the cookies associated with the document.document.referrer
: Returns the URI of the document that is linked to the current document.window.name
: Returns the name of the window.history.pushState()
andhistory.replaceState()
: Allow manipulation of the browser history.
TypeScript and React sources
State Variable
defined using the
useState
hook or other state management libraries.e.g.,
const [inputValue, setInputValue] = useState('');
Event Handler
functions that handle events like
onChange
,onClick
,onSubmit
, etc.e.g.,
const handleInputChange = (event) => { ... }
Input Element
where the user types their input
e.g.,
<input type="text" value={inputValue} onChange={handleInputChange} />
Form Elements
- HTML elements like
<input>
,<textarea>
, and<select>
. These elements are often sources of user input.
- HTML elements like
Props
It is a pattern to share information between a parent component and a child component. User input can be passed down as props from a parent component.
e.g.,
const MyComponent = ({ initialValue }) => { ... }
DOM-XSS sinks
These are some sinks that can lead to DOM-based XSS vulnerabilities:
document.write()
anddocument.writeln()
: Write directly to the document.element.innerHTML
andelement.outerHTML
: Allow manipulation of the HTML content of elements.element.insertAdjacentHTML()
: Inserts HTML at specified positions relative to the element.
JavaScript Injection sinks
Potentially dangerous functions that can execute JavaScript code:
eval()
: Executes a string of JavaScript code.function()
: Creates a new function from a string of code.setTimeout()
andsetInterval()
: Execute code after a delay or at intervals if passed a string.element.onevent
: Assigns event handler attributes.
Open-Redirection sinks
These properties can lead to open redirection vulnerabilities:
location
: Represents the location (URL) of the document.location.href
: Gets/sets the entire URL.location.assign()
andlocation.replace()
: Navigate to a new URL.element.src
: Sets the source of an element, such as an iframe or image.
Python and Django/Flask
Common Sources
request.GET['input']
: Retrieves query parameters.request.form['input']
: Retrieves form data.request.cookies['cookie_name']
: Retrieves cookies.
Sinks
cursor.execute(query)
: Executes a database command.render_template('template.html')
: Renders a template.subprocess.call('command')
: Executes a shell command.
Java and Spring
Common Sources
@RequestParam String input
: Retrieves request parameters.request.getParameter("input")
: Retrieves request parameters.request.getCookies()
: Retrieves cookies.
Sinks
jdbcTemplate.update(query)
: Executes a database update.response.getWriter().write(output)
: Writes to the HTTP response.Runtime.getRuntime().exec(command)
: Executes a system command.
C# and ASP.NET
Common Sources
Request.QueryString["input"]
: Retrieves query string parameters.Request.Form["input"]
: Retrieves form data.Request.Cookies["cookie_name"]
: Retrieves cookies.
Sinks
sqlCommand.ExecuteNonQuery()
: Executes a database command.Response.Write(output)
: Writes to the HTTP response.Process.Start(command)
: Starts a new process.
Steps to Implement Taint Analysis
Identify Sources: Begin by mapping out where user inputs enter your system. This could be through form fields, API endpoints, or other interfaces.
Trace the Flow: Follow the data as it moves through your system. Look for functions and methods that process or manipulate this data.
Identify Sinks: Determine where the data ends up, whether it’s being stored, displayed, or used in critical operations.
Analyze and Mitigate: Look for patterns where data might be mishandled. Ensure that all data reaching sinks is properly validated and sanitized to prevent vulnerabilities.
Tools to Aid
There are various tools available to help identify sources and sinks.
PortSwigger Labs
PortSwigger offers practical labs where one can practice identifying sources and sinks: PortSwigger Labs
Semgrep
Semgrep is a powerful tool for rule-based scanning. It allows you to create custom rules to identify sources and sinks in your code. Read more about how Semgrep can be used: Semgrep Documentation
Burp Canary
Burp Canary, an extension in BurpSuite that's pre-installed in Burp's browser. This enhances sources and sinks analysis by injecting unique tokens ("canaries") into the requests and tracks their flow. This precise tracking highlights how user input (sources) moves through the system to critical endpoints (sinks), identifying potential vulnerabilities. This automation complements taint analysis. Read more at: Burp Canary
BurpSuite BCheck Scripts
For scenarios where a UI is available, you can develop a BCheck script in Burp Suite to automate the identification of sources and sinks while you casually browse the application. Here is an example script for JavaScript sinks:
metadata:
language: v2-beta
name: "JS sinks for DOM-XSS (passive)"
description: "JavaScript sink that could lead to DOM-XSS."
author: "Kaustubh"
tags: "passive"
given response then
if {latest.response} matches "document.write|document.writeln|document.domain|\.innerHTML|\.outerHTML|\.insertAdjacentHTML|\.onevent" then
report issue and continue:
severity: info
confidence: firm
detail: "JavaScript sink that could lead to DOM-XSS."
remediation: "Investigate if this sink can be used to do a DOM-XSS."
end if
Checkout more Bcheck scripts here
Conclusion
Understanding sources and sinks is crucial in identifying potential vulnerabilities in a system. By recognising where untrusted data enters (sources) and where it is executed or stored (sinks), can safeguard against attacks.