JS: Functionality from untrusted sources query (CWE-830)

This commit is contained in:
Stephan Brandauer
2022-02-14 09:47:54 +01:00
parent e42f759f6b
commit 6722c17bb0
6 changed files with 138 additions and 0 deletions

View File

@@ -173,6 +173,24 @@ module HTML {
DocumentElement() { getName() = "html" }
}
/**
* An HTML `<iframe>` element.
*
* Example:
*
* ```
* <iframe src="https://test.local/somepage.html"></iframe>
* ```
*/
class IframeElement extends Element {
IframeElement() { getName() = "iframe" }
/**
* Gets the value of the `src` attribute.
*/
string getSourcePath() { result = getAttributeByName("src").getValue() }
}
/**
* An HTML `<script>` element.
*
@@ -207,6 +225,11 @@ module HTML {
*/
string getSourcePath() { result = getAttributeByName("src").getValue() }
/**
* Gets the value of the `integrity` attribute.
*/
string getIntegrityDigest() { result = getAttributeByName("integrity").getValue() }
/**
* Gets the folder relative to which the `src` attribute is resolved.
*/

View File

@@ -0,0 +1,41 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Including functionality from an external source via an http link may
allow an attacker to inject malicious code via a MITM (man-in-the-middle) attack.
</p>
</overview>
<recommendation>
<p>
When including external pages or behaviour, use <em>https</em> links (instead of http)
to be certain that you are getting a response from the intended server, not
someone else.
</p>
<p>
Using http links is unsafe because the request sent may be intercepted by an attacker,
and malicious data may be sent back in reply.
</p>
</recommendation>
<references>
<li>
MDN — Subresource Integrity: <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity">
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,57 @@
/**
* @name Inclusion of untrusted functionality by a HTML element.
* @description Including untrusted functionality by a HTML element
* opens up for potential man-in-the-middle attacks.
* @kind problem
* @problem.severity warning
* @security-severity 8.1
* @precision high
* @id js/functionality-from-untrusted-source
* @tags security
* external/cwe/cwe-830
*/
import javascript
import semmle.javascript.HTML
bindingset[host]
predicate isAllowedHost(string host) { host.toLowerCase().regexpMatch("localhost(:[0-9]+)?/.*") }
bindingset[path]
predicate isUntrustedSourcePath(string path) {
path.substring(0, 2) = "//"
or
exists(string hostPath | hostPath = path.regexpCapture("http://(.*)", 1) |
not isAllowedHost(hostPath)
)
}
abstract class IncludesUntrustedContent extends HTML::Element {
IncludesUntrustedContent() { this = this }
/** Gets an explanation why this source is untrusted. */
abstract string getProblem();
}
/** A script element that refers to untrusted content. */
class ScriptElementWithUntrustedContent extends IncludesUntrustedContent, HTML::ScriptElement {
ScriptElementWithUntrustedContent() {
isUntrustedSourcePath(this.getSourcePath()) and
not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest)
}
override string getProblem() {
result = "script elements should use an https link and/or use the integrity attribute"
}
}
/** An iframe element that includes untrusted content. */
class IframeElementWithUntrustedContent extends HTML::IframeElement, IncludesUntrustedContent {
IframeElementWithUntrustedContent() { isUntrustedSourcePath(this.getSourcePath()) }
override string getProblem() { result = "iframe elements should use an https link" }
}
from IncludesUntrustedContent s, string problem
where problem = s.getProblem()
select s, "HTML-element imports untrusted content (" + problem + ")"

View File

@@ -0,0 +1,3 @@
| test.html:6:9:6:56 | <script>...</> | HTML-element imports untrusted content (script elements should use an https link and/or use the integrity attribute) |
| test.html:9:9:9:58 | <iframe>...</> | HTML-element imports untrusted content (iframe elements should use an https link) |
| test.html:11:9:11:53 | <iframe>...</> | HTML-element imports untrusted content (iframe elements should use an https link) |

View File

@@ -0,0 +1 @@
Security/CWE-830/FunctionalityFromUntrustedSource.ql

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="http://test.local/foo.js"></script>> <!-- NOT OK -->
<script src="http://test.local/foo.js" integrity="some-integrity-hash"></script>> <!-- OK (integrity digest present) -->
<script src="https://test.local/bar.js"></script>> <!-- OK (https) -->
<iframe src="http://test.local/foo.html"></iframe> <!-- NOT OK -->
<iframe src="https://test.local/foo.html"></iframe> <!-- OK (https) -->
<iframe src="//test.local/foo.html"></iframe> <!-- NOT OK (protocol-relative url) -->
</body>
</html>