new Experimental query ClipboardBasedXss

This commit is contained in:
Daniel Santos
2021-08-17 12:57:26 -05:00
parent 88372df125
commit 5e155d25b1
3 changed files with 153 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Directly pasting user input from the clipboard to a webpage
without properly sanitizing the input first, allows for a cross-site scripting vulnerability.
</p>
</overview>
<recommendation>
<p>
To guard against cross-site scripting, consider using contextual output encoding/escaping before
writing user input to the page, or one of the other solutions that are mentioned in the
references.
</p>
</recommendation>
<example>
<p>
The following example shows a div element whose HTML content comes directly from the clipboard being written to the DOM,
leaving the website vulnerable to cross-site scripting.
</p>
<sample src="examples/clipboard-xss-sample.js" />
</example>
<references>
<li>
OWASP:
<a href="https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html">DOM based
XSS Prevention Cheat Sheet</a>.
</li>
<li>
OWASP:
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>
OWASP
<a href="https://www.owasp.org/index.php/DOM_Based_XSS">DOM Based XSS</a>.
</li>
<li>
OWASP
<a href="https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting">Types of Cross-Site
Scripting</a>.
</li>
<li>
Wikipedia: <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-site scripting</a>.
</li>
<li>
Securitum:
<a href="https://research.securitum.com/the-curious-case-of-copy-paste/">Clipboard security research</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,78 @@
/**
* @name Client-side clipboard-based cross-site scripting
* @description Pasting clipboard input directly to the DOM without proper sanitization allows for
* a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @security-severity 3.1
* @precision high
* @id js/clipboard-xss
* @tags security
* external/cwe/cwe-079
*/
import javascript
import DataFlow
import semmle.javascript.security.dataflow.DomBasedXss
import DataFlow::PathGraph
/*
* Gets references to clipboardData DataTransfer objects
* https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
*/
SourceNode clipboardDataTransferSource(TypeTracker t) {
t.start() and
exists(DataFlow::PropRead pr | pr.getPropertyName() = "clipboardData" and pr.flowsTo(result))
or
exists(TypeTracker t2 | result = clipboardDataSource(t2).track(t2, t))
}
SourceNode clipboardDataTransferSource() {
result = clipboardDataTransferSource(TypeTracker::end())
}
/*
* Gets references to the result of a call to getData on a DataTransfer object
* https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData
*/
SourceNode clipboardDataSource(TypeTracker t) {
t.start() and
clipboardDataTransferSource().getAMethodCall("getData").flowsTo(result)
or
exists(TypeTracker t2 | result = clipboardDataSource(t2).track(t2, t))
}
SourceNode clipboardDataSource() { result = clipboardDataSource(TypeTracker::end()) }
class ClipboardSource extends DataFlow::Node {
ClipboardSource() { this = clipboardDataSource() }
}
class ClipboardHtmlInjectionConfiguration extends DomBasedXss::HtmlInjectionConfiguration {
override predicate isSource(DataFlow::Node source) { source instanceof ClipboardSource }
}
class ClipboardJQueryHtmlOrSelectorInjectionConfiguration extends DomBasedXss::JQueryHtmlOrSelectorInjectionConfiguration {
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
// Reuse any source not derived from location
source instanceof ClipboardSource and
(
label.isTaint()
or
label.isData() // Require transformation before reaching sink
)
}
}
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where
(
cfg instanceof ClipboardHtmlInjectionConfiguration or
cfg instanceof ClipboardJQueryHtmlOrSelectorInjectionConfiguration
) and
cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
sink.getNode().(DomBasedXss::Sink).getVulnerabilityKind() + " vulnerability due to $@.",
source.getNode(), "user-provided clipboard value"

View File

@@ -0,0 +1,18 @@
function paste(e) {
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
const text = clipboardData.getData('text/plain');
const html = clipboardData.getData('text/html');
if (!text && !html) return;
e.preventDefault();
const div = document.createElement('div');
if (html) {
div.innerHTML = html;
} else {
div.textContent = text;
}
document.body.append(div);
}