Compare commits

...

1 Commits

Author SHA1 Message Date
Andrew Eisenberg
df35d97aca WIP 2022-12-06 09:28:10 -08:00
7 changed files with 66 additions and 138 deletions

View File

@@ -7,38 +7,47 @@
private import javascript
private import BaseScoring
private import EndpointFeatures as EndpointFeatures
private import FeaturizationConfig
private import PromptConfiguration
private import EndpointTypes
private string getACompatibleModelChecksum() {
availableMlModels(result, "javascript", _, "atm-endpoint-scoring")
}
// class RelevantFeaturizationConfig extends FeaturizationConfig {
// RelevantFeaturizationConfig() { this = "RelevantFeaturization" }
// override DataFlow::Node getAnEndpointToFeaturize() {
// getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _)
// or
// getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result)
// }
// }
module ModelScoring {
/**
* A featurization config that only featurizes new candidate endpoints that are part of a flow
* path.
*/
class RelevantFeaturizationConfig extends FeaturizationConfig {
RelevantFeaturizationConfig() { this = "RelevantFeaturization" }
override DataFlow::Node getAnEndpointToFeaturize() {
getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _)
or
getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result)
}
predicate getARequestedEndpoint(DataFlow::Node node, string prompt) {
exists(PromptConfiguration cfg | cfg.getPrompt(node) = prompt and cfg.getAnEndpointToFeaturize() = node)
}
DataFlow::Node getARequestedEndpoint() {
result = any(FeaturizationConfig cfg).getAnEndpointToFeaturize()
predicate endpointScores(DataFlow::Node endpoint, int encodedEndpointType, float score) {
internalEnpointScores(endpoint, mapEndpointType(encodedEndpointType)) and mapScore(score, mapEndpointType(encodedEndpointType))
}
private int getARequestedEndpointType() { result = any(EndpointType type).getEncoding() }
predicate internalEnpointScores(DataFlow::Node endpoint, string endpointType) =
remoteScoreEndpoints(getARequestedEndpoint/2)(endpoint, endpointType)
private string mapEndpointType(int encodedEndpointType) {
(result = "no sink" and encodedEndpointType = 0) or
(result = "xss sink" and encodedEndpointType = 1) or
(result = "nosql sink" and encodedEndpointType = 2) or
(result = "sql sink" and encodedEndpointType = 3) or
(result = "tainted path sink" and encodedEndpointType = 4)
}
predicate endpointScores(DataFlow::Node endpoint, int encodedEndpointType, float score) =
scoreEndpoints(getARequestedEndpoint/0, EndpointFeatures::tokenFeatures/3,
EndpointFeatures::getASupportedFeatureName/0, getARequestedEndpointType/0,
getACompatibleModelChecksum/0)(endpoint, encodedEndpointType, score)
private predicate mapScore(float score, string endpointType) {
((endpointType = "xss sink" or endpointType = "nosql sink" or endpointType = "sql sink" or
endpointType = "tainted path sink") and score = 1.0) /*or (score = 0.0 and any(endpointType)) */
}
}
/**
@@ -94,7 +103,6 @@ class EndpointScoringResults extends ScoringResults {
or
result = "predicted" and getCfg().isEffectiveSource(source)
}
/**
* Get a string representing why ATM included the given sink in the dataflow analysis.
*
@@ -139,15 +147,15 @@ class EndpointScoringResults extends ScoringResults {
}
}
module Debugging {
query predicate hopInputEndpoints(DataFlow::Node endpoint) {
endpoint = ModelScoring::getARequestedEndpoint()
}
// module Debugging {
// query predicate hopInputEndpoints(DataFlow::Node endpoint) {
// endpoint = ModelScoring::getARequestedEndpoint()
// }
query predicate endpointScores = ModelScoring::endpointScores/3;
// query predicate endpointScores = ModelScoring::endpointScores/3;
query predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
any(ScoringResults scoringResults).shouldResultBeIncluded(source, sink) and
any(DataFlow::Configuration cfg).hasFlow(source, sink)
}
}
// query predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
// any(ScoringResults scoringResults).shouldResultBeIncluded(source, sink) and
// any(DataFlow::Configuration cfg).hasFlow(source, sink)
// }
// }

View File

@@ -0,0 +1,25 @@
import javascript
private import BaseScoring
import FeaturizationConfig
class PromptConfiguration extends FeaturizationConfig {
PromptConfiguration() {
this = "PromptConfiguration"
}
// abstract predicate getANodeAndPrompt(DataFlow::Node node, string prompt);
string getPrompt(DataFlow::Node node) {
result = "# Examples of security vulnerability sinks and non-sinks\n|Dataflow node|Neighborhood|Classification|\n|---|---|---|\n| `bid` | `const body = <a href=https://ampbyexample.com target=_blank> <amp-img alt=AMP Ad height=250 src=//localhost:9876/amp4test/request-bank/${bid}/deposit/image width=300></amp-img> </a> <amp-pixel src=//localhost:9876/amp4test/request-bank/${bid}/deposit/pixel/foo?cid=CLIENT_ID(a)></amp-pixel>` | xss sink |\n| `nick` | `irc.me = nick; irc.nick(nick); irc.user(username, realname);` | non-sink || `hash` | `componentDidMount() { const [, hash] = location.href.split(#) this.setState({ hash }) }` | `"
+ extractString(node) + "` | "
}
string extractString(DataFlow::Node node) {
result = node.getStringValue()
}
override DataFlow::Node getAnEndpointToFeaturize() {
getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _)
or
getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result)
}
}

View File

@@ -1,24 +0,0 @@
/**
* For internal use only.
*
* @name NoSQL database query built from user-controlled sources (experimental)
* @description Building a database query from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
* @kind path-problem
* @scored
* @problem.severity error
* @security-severity 8.8
* @id js/ml-powered/nosql-injection
* @tags experimental security
* external/cwe/cwe-943
*/
import ATM::ResultsInfo
import DataFlow::PathGraph
import experimental.adaptivethreatmodeling.NosqlInjectionATM
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
where cfg.hasBoostedFlowPath(source, sink, score)
select sink.getNode(), source, sink,
"(Experimental) This may be a database query that depends on $@. Identified using machine learning.",
source.getNode(), "a user-provided value", score

View File

@@ -1,28 +0,0 @@
/**
* For internal use only.
*
* @name Uncontrolled data used in path expression (experimental)
* @description Accessing paths influenced by users can allow an attacker to access
* unexpected resources.
* @kind path-problem
* @scored
* @problem.severity error
* @security-severity 7.5
* @id js/ml-powered/path-injection
* @tags experimental security
* external/cwe/cwe-022
* external/cwe/cwe-023
* external/cwe/cwe-036
* external/cwe/cwe-073
* external/cwe/cwe-099
*/
import ATM::ResultsInfo
import DataFlow::PathGraph
import experimental.adaptivethreatmodeling.TaintedPathATM
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
where cfg.hasBoostedFlowPath(source, sink, score)
select sink.getNode(), source, sink,
"(Experimental) This may be a path that depends on $@. Identified using machine learning.",
source.getNode(), "a user-provided value", score

View File

@@ -1,25 +0,0 @@
/**
* For internal use only.
*
* @name Client-side cross-site scripting (experimental)
* @description Writing user input directly to the DOM allows for
* a cross-site scripting vulnerability.
* @kind path-problem
* @scored
* @problem.severity error
* @security-severity 6.1
* @id js/ml-powered/xss
* @tags experimental security
* external/cwe/cwe-079
*/
import javascript
import ATM::ResultsInfo
import DataFlow::PathGraph
import experimental.adaptivethreatmodeling.XssATM
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
where cfg.hasBoostedFlowPath(source, sink, score)
select sink.getNode(), source, sink,
"(Experimental) This may be a cross-site scripting vulnerability due to $@. Identified using machine learning.",
source.getNode(), "a user-provided value", score

View File

@@ -1,25 +0,0 @@
/**
* For internal use only.
*
* @name DOM text reinterpreted as HTML (experimental)
* @description Reinterpreting text from the DOM as HTML can lead
* to a cross-site scripting vulnerability.
* @kind path-problem
* @scored
* @problem.severity error
* @security-severity 6.1
* @id js/ml-powered/xss-through-dom
* @tags experimental security
* external/cwe/cwe-079 external/cwe/cwe-116
*/
import javascript
import ATM::ResultsInfo
import DataFlow::PathGraph
import experimental.adaptivethreatmodeling.XssThroughDomATM
from AtmConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink, float score
where cfg.hasBoostedFlowPath(source, sink, score)
select sink.getNode(), source, sink,
"(Experimental) $@ may be reinterpreted as HTML without escaping meta-characters. Identified using machine learning.",
source.getNode(), "DOM text", score

View File

@@ -1,19 +1,16 @@
/**
* For internal use only.
*
* @name SQL database query built from user-controlled sources (experimental)
* @description Building a database query from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
* @kind path-problem
* @scored
* @problem.severity error
* @security-severity 8.8
* @id js/ml-powered/sql-injection
* @tags experimental security
* external/cwe/cwe-089
* @id js/ml-powered/silliness
*/
import javascript
import experimental.adaptivethreatmodeling.SqlInjectionATM
import experimental.adaptivethreatmodeling.PromptConfiguration
import ATM::ResultsInfo
import DataFlow::PathGraph