-
Notifications
You must be signed in to change notification settings - Fork 1.8k
JS: add simple query for detecting sensitive files downloaded over insecure connection #3689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
5b49131
add simple query for detecting sensitive files downloaded over unsecu…
erik-krogh 8225adc
move TODOs
erik-krogh 056a7e8
refactor into customizations module - and move curl download to a Cli…
erik-krogh 3f95710
improve alert message - and autoformat
erik-krogh 9780fcf
fix ftp protocol regexp
erik-krogh 57d2226
typo
erik-krogh 908edb3
unsecure -> insecure
erik-krogh 1751fb6
add missing qldoc
erik-krogh 4d1920e
add .js and .py files to js/insecure-download
erik-krogh fe9aa24
add qhelp
erik-krogh 8682918
add change note
erik-krogh e8db624
add .jar and .war to the list of sensitive files for js/insecure-down…
erik-krogh 5e060fa
Apply suggestions from code review
erik-krogh fb5e13b
Apply suggestions from doc review
erik-krogh 7a1c161
Merge branch 'js-team-sprint' into https-fix
erik-krogh 27a20b2
Merge branch 'https-fix' of github.com:erik-krogh/ql into https-fix
erik-krogh 7d6dac4
Merge branch 'js-team-sprint' into https-fix
erik-krogh 0f5ef2c
Merge branch 'js-team-sprint' into https-fix
erik-krogh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<!DOCTYPE qhelp PUBLIC | ||
"-//Semmle//qhelp//EN" | ||
"qhelp.dtd"> | ||
<qhelp> | ||
<overview> | ||
<p> | ||
Downloading executeables or other sensitive files over an unencrypted connection | ||
can leave a server open to man-in-the-middle attacks (MITM). | ||
Such an attack can allow an attacker to insert arbitrary content | ||
into the downloaded file, and in the worst case, allow the attacker to execute | ||
arbitrary code on the vulnerable system. | ||
</p> | ||
</overview> | ||
<recommendation> | ||
<p> | ||
Use a secure transfer protocol when downloading executables or other sensitive files. | ||
</p> | ||
</recommendation> | ||
<example> | ||
<p> | ||
In this example, a server downloads a shell script from a remote URL using the <code>node-fetch</code> | ||
library, and then executes this shell script. | ||
</p> | ||
<sample src="examples/insecure-download.js" /> | ||
<p> | ||
The HTTP protocol is vulnerable to MITM, and thus an attacker could potentially replace the downloaded | ||
shell script with arbitrary code, which gives the attacker complete control over the system. | ||
</p> | ||
<p> | ||
The issue has been fixed in the example below by replacing the HTTP protocol with the HTTPS protocol. | ||
</p> | ||
<sample src="examples/insecure-download.js" /> | ||
</example> | ||
|
||
<references> | ||
<li>OWASP: <a href="https://owasp.org/www-community/attacks/Man-in-the-middle_attack">Man-in-the-middle attack</a>.</li> | ||
</references> | ||
</qhelp> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* @name Download of sensitive file through insecure connection | ||
* @description Downloading executables and other sensitive files over an insecure connection | ||
* opens up for potential man-in-the-middle attacks. | ||
* @kind path-problem | ||
* @problem.severity error | ||
* @precision high | ||
* @id js/insecure-download | ||
* @tags security | ||
* external/cwe/cwe-829 | ||
*/ | ||
|
||
import javascript | ||
import semmle.javascript.security.dataflow.InsecureDownload::InsecureDownload | ||
import DataFlow::PathGraph | ||
|
||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink | ||
where cfg.hasFlowPath(source, sink) | ||
select sink.getNode(), source, sink, "$@ of sensitive file from $@.", | ||
sink.getNode().(Sink).getDownloadCall(), "Download", source.getNode(), "HTTP source" |
6 changes: 6 additions & 0 deletions
6
javascript/ql/src/Security/CWE-829/examples/insecure-download.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const fetch = require("node-fetch"); | ||
const cp = require("child_process"); | ||
|
||
fetch('http://mydownload.example.org/myscript.sh') | ||
.then(res => res.text()) | ||
.then(script => cp.execSync(script)); |
6 changes: 6 additions & 0 deletions
6
javascript/ql/src/Security/CWE-829/examples/secure-download.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const fetch = require("node-fetch"); | ||
const cp = require("child_process"); | ||
|
||
fetch('https://mydownload.example.org/myscript.sh') | ||
.then(res => res.text()) | ||
.then(script => cp.execSync(script)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Provides a taint tracking configuration for reasoning about download of sensitive file through insecure connection. | ||
* | ||
* Note, for performance reasons: only import this file if | ||
* `InsecureDownload::Configuration` is needed, otherwise | ||
* `InsecureDownloadCustomizations` should be imported instead. | ||
*/ | ||
|
||
import javascript | ||
|
||
/** | ||
* Classes and predicates for reasoning about download of sensitive file through insecure connection vulnerabilities. | ||
*/ | ||
module InsecureDownload { | ||
import InsecureDownloadCustomizations::InsecureDownload | ||
|
||
/** | ||
* A taint tracking configuration for download of sensitive file through insecure connection. | ||
*/ | ||
class Configuration extends DataFlow::Configuration { | ||
Configuration() { this = "InsecureDownload" } | ||
|
||
override predicate isSource(DataFlow::Node source) { source instanceof Source } | ||
|
||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/** | ||
* Provides default sources, sinks and sanitizers for reasoning about | ||
* download of sensitive file through insecure connection, as well as | ||
* extension points for adding your own. | ||
*/ | ||
|
||
import javascript | ||
|
||
/** | ||
* Classes and predicates for reasoning about download of sensitive file through insecure connection vulnerabilities. | ||
*/ | ||
module InsecureDownload { | ||
/** | ||
* A data flow source for download of sensitive file through insecure connection. | ||
*/ | ||
abstract class Source extends DataFlow::Node { } | ||
|
||
/** | ||
* A data flow sink for download of sensitive file through insecure connection. | ||
*/ | ||
abstract class Sink extends DataFlow::Node { | ||
/** | ||
* Gets the call that downloads the sensitive file. | ||
*/ | ||
abstract DataFlow::Node getDownloadCall(); | ||
} | ||
|
||
/** | ||
* A sanitizer for download of sensitive file through insecure connection. | ||
*/ | ||
abstract class Sanitizer extends DataFlow::Node { } | ||
|
||
/** | ||
* A HTTP or FTP URL that refers to a file with a sensitive file extension, | ||
* seen as a source for download of sensitive file through insecure connection. | ||
*/ | ||
class SensitiveFileUrl extends Source { | ||
SensitiveFileUrl() { | ||
exists(string str | str = this.getStringValue() | | ||
str.regexpMatch("http://.*|ftp://.*") and | ||
exists(string suffix | suffix = unsafeExtension() | | ||
str.suffix(str.length() - suffix.length() - 1).toLowerCase() = "." + suffix | ||
) | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Gets a file-extension that can potentially be dangerous. | ||
* | ||
* Archives are included, because they often contain source-code. | ||
*/ | ||
string unsafeExtension() { | ||
result = | ||
["exe", "dmg", "pkg", "tar.gz", "zip", "sh", "bat", "cmd", "app", "apk", "msi", "dmg", | ||
"tar.gz", "zip", "js", "py", "jar", "war"] | ||
} | ||
|
||
/** | ||
* A url downloaded by a client-request, seen as a sink for download of | ||
* sensitive file through insecure connection.a | ||
*/ | ||
class ClientRequestURL extends Sink { | ||
ClientRequest request; | ||
|
||
ClientRequestURL() { this = request.getUrl() } | ||
|
||
override DataFlow::Node getDownloadCall() { result = request } | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
javascript/ql/test/query-tests/Security/CWE-829/InsecureDownload.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
nodes | ||
| insecure-download.js:5:16:5:28 | installer.url | | ||
| insecure-download.js:5:16:5:28 | installer.url | | ||
| insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | | ||
| insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | | ||
| insecure-download.js:15:18:15:40 | buildTo ... llerUrl | | ||
| insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | | ||
| insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | | ||
| insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | | ||
| insecure-download.js:36:9:36:45 | url | | ||
| insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | | ||
| insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | | ||
| insecure-download.js:37:23:37:25 | url | | ||
| insecure-download.js:37:23:37:25 | url | | ||
| insecure-download.js:39:26:39:28 | url | | ||
| insecure-download.js:39:26:39:28 | url | | ||
| insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | | ||
| insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | | ||
| insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | | ||
edges | ||
| insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | insecure-download.js:15:18:15:40 | buildTo ... llerUrl | | ||
| insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | insecure-download.js:15:18:15:40 | buildTo ... llerUrl | | ||
| insecure-download.js:15:18:15:40 | buildTo ... llerUrl | insecure-download.js:5:16:5:28 | installer.url | | ||
| insecure-download.js:15:18:15:40 | buildTo ... llerUrl | insecure-download.js:5:16:5:28 | installer.url | | ||
| insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | | ||
| insecure-download.js:36:9:36:45 | url | insecure-download.js:37:23:37:25 | url | | ||
| insecure-download.js:36:9:36:45 | url | insecure-download.js:37:23:37:25 | url | | ||
| insecure-download.js:36:9:36:45 | url | insecure-download.js:39:26:39:28 | url | | ||
| insecure-download.js:36:9:36:45 | url | insecure-download.js:39:26:39:28 | url | | ||
| insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | insecure-download.js:36:9:36:45 | url | | ||
| insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | insecure-download.js:36:9:36:45 | url | | ||
| insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | | ||
#select | ||
| insecure-download.js:5:16:5:28 | installer.url | insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | insecure-download.js:5:16:5:28 | installer.url | $@ of sensitive file from $@. | insecure-download.js:5:9:5:44 | nugget( ... => { }) | Download | insecure-download.js:9:27:9:138 | 'http:/ ... ll.exe' | HTTP source | | ||
| insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | $@ of sensitive file from $@. | insecure-download.js:30:5:30:43 | nugget( ... e.APK") | Download | insecure-download.js:30:12:30:42 | "http:/ ... fe.APK" | HTTP source | | ||
| insecure-download.js:37:23:37:25 | url | insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | insecure-download.js:37:23:37:25 | url | $@ of sensitive file from $@. | insecure-download.js:37:5:37:42 | cp.exec ... () {}) | Download | insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | HTTP source | | ||
| insecure-download.js:39:26:39:28 | url | insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | insecure-download.js:39:26:39:28 | url | $@ of sensitive file from $@. | insecure-download.js:39:5:39:46 | cp.exec ... () {}) | Download | insecure-download.js:36:15:36:45 | "http:/ ... fe.APK" | HTTP source | | ||
| insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | $@ of sensitive file from $@. | insecure-download.js:41:5:41:42 | nugget( ... e.APK") | Download | insecure-download.js:41:12:41:41 | "ftp:// ... fe.APK" | HTTP source | |
1 change: 1 addition & 0 deletions
1
javascript/ql/test/query-tests/Security/CWE-829/InsecureDownload.qlref
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Security/CWE-829/InsecureDownload.ql |
42 changes: 42 additions & 0 deletions
42
javascript/ql/test/query-tests/Security/CWE-829/insecure-download.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
const nugget = require('nugget'); | ||
|
||
function foo() { | ||
function downloadTools(installer) { | ||
nugget(installer.url, {}, () => { }) // NOT OK | ||
} | ||
var constants = { | ||
buildTools: { | ||
installerUrl: 'http://download.microsoft.com/download/5/f/7/5f7acaeb-8363-451f-9425-68a90f98b238/visualcppbuildtools_full.exe' | ||
} | ||
} | ||
function getBuildToolsInstallerPath() { | ||
const buildTools = constants.buildTools | ||
return { | ||
url: buildTools.installerUrl | ||
} | ||
} | ||
|
||
downloadTools(getBuildToolsInstallerPath()) | ||
} | ||
|
||
|
||
const request = require('request'); | ||
|
||
function bar() { | ||
request('http://www.google.com', function () { }); // OK | ||
|
||
nugget("https://download.microsoft.com/download/5/f/7/5f7acaeb-8363-451f-9425-68a90f98b238/visualcppbuildtools_full.exe") // OK | ||
|
||
nugget("http://example.org/unsafe.APK") // NOT OK | ||
} | ||
|
||
var cp = require("child_process") | ||
|
||
function baz() { | ||
var url = "http://example.org/unsafe.APK"; | ||
cp.exec("curl " + url, function () {}); // NOT OK | ||
|
||
cp.execFile("curl", [url], function () {}); // NOT OK | ||
|
||
nugget("ftp://example.org/unsafe.APK") // NOT OK | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about
.jar
and.war
files?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, those after often used as executeables.