Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 056a7e8

Browse files
committed
refactor into customizations module - and move curl download to a ClientRequest
1 parent 8225adc commit 056a7e8

4 files changed

Lines changed: 127 additions & 39 deletions

File tree

javascript/ql/src/Security/CWE-829/UnsecureDownload.ql

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,47 +11,9 @@
1111
*/
1212

1313
import javascript
14+
import semmle.javascript.security.dataflow.UnsecureDownload::UnsecureDownload
1415
import DataFlow::PathGraph
1516

16-
class Configuration extends DataFlow::Configuration {
17-
Configuration() { this = "HTTP/HTTPS" }
18-
19-
override predicate isSource(DataFlow::Node source) {
20-
exists(string str | str = source.getStringValue() |
21-
str.regexpMatch("http://.*|ftp://.'") and
22-
exists(string suffix | suffix = unsafeSuffix() |
23-
str.suffix(str.length() - suffix.length() - 1).toLowerCase() = "." + suffix
24-
)
25-
)
26-
}
27-
28-
override predicate isSink(DataFlow::Node sink) {
29-
exists(ClientRequest request | sink = request.getUrl())
30-
or
31-
exists(SystemCommandExecution cmd |
32-
cmd.getACommandArgument().getStringValue() = "curl" or
33-
cmd
34-
.getACommandArgument()
35-
.(StringOps::ConcatenationRoot)
36-
.getConstantStringParts()
37-
.regexpMatch("curl .*")
38-
|
39-
sink = cmd.getArgumentList().getALocalSource().getAPropertyWrite().getRhs() or
40-
sink = cmd.getACommandArgument().(StringOps::ConcatenationRoot).getALeaf()
41-
)
42-
}
43-
}
44-
45-
/**
46-
* Gets a file-suffix
47-
*/
48-
string unsafeSuffix() {
49-
// including arcives, because they often contain source-code.
50-
result =
51-
["exe", "dmg", "pkg", "tar.gz", "zip", "sh", "bat", "cmd", "app", "apk", "msi", "dmg", "tar.gz",
52-
"zip"]
53-
}
54-
5517
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
5618
where cfg.hasFlowPath(source, sink)
5719
select sink.getNode(), source, sink, "Download of file from $@.", source.getNode(), "HTTP source"

javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,32 @@ module ClientRequest {
633633

634634
override DataFlow::Node getADataNode() { none() }
635635
}
636+
637+
/**
638+
* A shell execution of `curl` that downloads some file.
639+
*/
640+
class CurlDownload extends ClientRequest::Range {
641+
SystemCommandExecution cmd;
642+
643+
CurlDownload() {
644+
this = cmd and
645+
(
646+
cmd.getACommandArgument().getStringValue() = "curl" or
647+
cmd
648+
.getACommandArgument()
649+
.(StringOps::ConcatenationRoot)
650+
.getConstantStringParts()
651+
.regexpMatch("curl .*")
652+
)
653+
}
654+
655+
override DataFlow::Node getUrl() {
656+
result = cmd.getArgumentList().getALocalSource().getAPropertyWrite().getRhs() or
657+
result = cmd.getACommandArgument().(StringOps::ConcatenationRoot).getALeaf()
658+
}
659+
660+
override DataFlow::Node getHost() { none() }
661+
662+
override DataFlow::Node getADataNode() { none() }
663+
}
636664
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Provides a taint tracking configuration for reasoning about download of sensitive file through unsecure connection.
3+
*
4+
* Note, for performance reasons: only import this file if
5+
* `UnsecureDownload::Configuration` is needed, otherwise
6+
* `UnsecureDownloadCustomizations` should be imported instead.
7+
*/
8+
9+
import javascript
10+
11+
module UnsecureDownload {
12+
import UnsecureDownloadCustomizations::UnsecureDownload
13+
14+
/**
15+
* A taint tracking configuration for download of sensitive file through unsecure connection.
16+
*/
17+
class Configuration extends DataFlow::Configuration {
18+
Configuration() { this = "HTTP/HTTPS" }
19+
20+
override predicate isSource(DataFlow::Node source) {
21+
source instanceof Source
22+
}
23+
24+
override predicate isSink(DataFlow::Node sink) {
25+
sink instanceof Sink
26+
}
27+
}
28+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Provides default sources, sinks and sanitizers for reasoning about
3+
* download of sensitive file through unsecure connection, as well as
4+
* extension points for adding your own.
5+
*/
6+
7+
import javascript
8+
9+
module UnsecureDownload {
10+
/**
11+
* A data flow source for download of sensitive file through unsecure connection.
12+
*/
13+
abstract class Source extends DataFlow::Node { }
14+
15+
/**
16+
* A data flow sink for download of sensitive file through unsecure connection.
17+
*/
18+
abstract class Sink extends DataFlow::Node {
19+
/**
20+
* Gets the call that downloads the sensitive file.
21+
*/
22+
abstract DataFlow::Node getDownloadCall();
23+
}
24+
25+
/**
26+
* A sanitizer for download of sensitive file through unsecure connection.
27+
*/
28+
abstract class Sanitizer extends DataFlow::Node { }
29+
30+
/**
31+
* A HTTP or FTP URL that refers to a file with a sensitive file extension,
32+
* seen as a source for download of sensitive file through unsecure connection.
33+
*/
34+
class SensitiveFileUrl extends Source {
35+
SensitiveFileUrl() {
36+
exists(string str | str = this.getStringValue() |
37+
str.regexpMatch("http://.*|ftp://.'") and
38+
exists(string suffix | suffix = unsafeExtension() |
39+
str.suffix(str.length() - suffix.length() - 1).toLowerCase() = "." + suffix
40+
)
41+
)
42+
}
43+
}
44+
45+
/**
46+
* Gets a file-extension that can potentially be dangerous.
47+
*
48+
* Archives are included, because they often contain source-code.
49+
*/
50+
string unsafeExtension() {
51+
result =
52+
["exe", "dmg", "pkg", "tar.gz", "zip", "sh", "bat", "cmd", "app", "apk", "msi", "dmg",
53+
"tar.gz", "zip"]
54+
}
55+
56+
/**
57+
* A url downloaded by a client-request, seen as a sink for download of
58+
* sensitive file through unsecure connection.a
59+
*/
60+
class ClientRequestURL extends Sink {
61+
ClientRequest request;
62+
ClientRequestURL() {
63+
this = request.getUrl()
64+
}
65+
66+
override DataFlow::Node getDownloadCall() {
67+
result = request
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)