copy-paste from our repo

This commit is contained in:
valeria-meli
2021-07-27 18:09:11 -03:00
parent d7c29791de
commit f3c0bf7826
3 changed files with 127 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Directly incorporating user input into an HTTP request without validating the input can facilitate
server side request forgery attacks, where the attacker essentially controls the request.
</p>
</overview>
<recommendation>
<p>
To guard against server side request forgery, it is advisable to avoid putting user input directly into a
network request. If using user input is necessary, then is mandatory to validate them. Only allow numeric and alphanumeric values.
URL encoding is not a solution in certain scenarios, such as, an architecture build over NGINX proxies.
</p>
</recommendation>
<example>
<p>
The following example shows an HTTP request parameter being used directly in a URL request without
validating the input, which facilitates an SSRF attack. The request <code>axios.get("https://example.com/current_api/"+target)</code> is
vulnerable since attackers can choose the value of <code>target</code> to be anything they want. For
instance, the attacker can choose <code>"../super_secret_api"</code> as the target, causing the
URL to become <code>"https://example.com/super_secret_api"</code>.
</p>
<p>
A request to <code>https://example.com/super_secret_api</code> may be problematic if that api is not
meant to be directly accessible from the attacker's machine.
</p>
<sample src="SSRF.js"/>
<p>
One way to remedy the problem is to validate the user input to only allow alphanumeric values:
</p>
<sample src="SSRFGood.js"/>
</example>
<references>
<li>OWASP: <a href="https://www.owasp.org/www-community/attacks/Server_Side_Request_Forgery">SSRF</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,18 @@
/**
* @id javascript/ssrf-path
* @kind path-problem
* @name Uncontrolled data used in network request
* @description Sending network requests with user-controlled data as part of the URL allows for request forgery attacks.
* @problem.severity error
* @precision medium
* @tags security
* external/cwe/cwe-918
*/
import javascript
import SSRF
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
where cfg.hasFlowPath(source, sink) and request = sink.getNode().(RequestForgery::Sink).getARequest()
select sink, source, sink, "The URL of this request depends on a user-provided value"

View File

@@ -0,0 +1,60 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgeryCustomizations
import semmle.javascript.security.dataflow.UrlConcatenation
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "SSRF" }
override predicate isSource(DataFlow::Node source) { source instanceof RequestForgery::Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgery::Sink }
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof RequestForgery::Sanitizer
}
override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) {
sanitizingPrefixEdge(source, sink)
}
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode nd) {
nd instanceof IntegerCheck or
nd instanceof ValidatorCheck
}
}
/**
* Number.isInteger is a sanitizer guard because a number can't be used to exploit a SSRF.
*/
class IntegerCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode{
IntegerCheck() {
this = DataFlow::globalVarRef("Number").getAMemberCall("isInteger")
}
override predicate sanitizes(boolean outcome, Expr e){
outcome = true and
e = getArgument(0).asExpr()
}
}
/**
* ValidatorCheck identifies if exists a call to validator's library methods.
* validator is a library which has a variety of input-validation functions. We are interesed in
* checking that source is a number (any type of number) or an alphanumeric value.
*/
class ValidatorCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
ValidatorCheck() {
exists(
DataFlow::SourceNode mod, string method |
mod = DataFlow::moduleImport("validator") and
this = mod.getAChainedMethodCall(method)
and method in ["isAlphanumeric", "isAlpha", "isDecimal", "isFloat",
"isHexadecimal", "isHexColor", "isInt", "isNumeric", "isOctal", "isUUID"]
)
}
override predicate sanitizes(boolean outcome, Expr e){
outcome = true and
e = getArgument(0).asExpr()
}
}