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 javascript
private import BaseScoring private import BaseScoring
private import EndpointFeatures as EndpointFeatures private import EndpointFeatures as EndpointFeatures
private import FeaturizationConfig private import PromptConfiguration
private import EndpointTypes private import EndpointTypes
private string getACompatibleModelChecksum() { private string getACompatibleModelChecksum() {
availableMlModels(result, "javascript", _, "atm-endpoint-scoring") 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 { 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() { predicate getARequestedEndpoint(DataFlow::Node node, string prompt) {
getCfg().isEffectiveSource(result) and any(DataFlow::Configuration cfg).hasFlow(result, _) exists(PromptConfiguration cfg | cfg.getPrompt(node) = prompt and cfg.getAnEndpointToFeaturize() = node)
or
getCfg().isEffectiveSink(result) and any(DataFlow::Configuration cfg).hasFlow(_, result)
}
} }
DataFlow::Node getARequestedEndpoint() { predicate endpointScores(DataFlow::Node endpoint, int encodedEndpointType, float score) {
result = any(FeaturizationConfig cfg).getAnEndpointToFeaturize() 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) = private predicate mapScore(float score, string endpointType) {
scoreEndpoints(getARequestedEndpoint/0, EndpointFeatures::tokenFeatures/3, ((endpointType = "xss sink" or endpointType = "nosql sink" or endpointType = "sql sink" or
EndpointFeatures::getASupportedFeatureName/0, getARequestedEndpointType/0, endpointType = "tainted path sink") and score = 1.0) /*or (score = 0.0 and any(endpointType)) */
getACompatibleModelChecksum/0)(endpoint, encodedEndpointType, score) }
} }
/** /**
@@ -94,7 +103,6 @@ class EndpointScoringResults extends ScoringResults {
or or
result = "predicted" and getCfg().isEffectiveSource(source) result = "predicted" and getCfg().isEffectiveSource(source)
} }
/** /**
* Get a string representing why ATM included the given sink in the dataflow analysis. * Get a string representing why ATM included the given sink in the dataflow analysis.
* *
@@ -139,15 +147,15 @@ class EndpointScoringResults extends ScoringResults {
} }
} }
module Debugging { // module Debugging {
query predicate hopInputEndpoints(DataFlow::Node endpoint) { // query predicate hopInputEndpoints(DataFlow::Node endpoint) {
endpoint = ModelScoring::getARequestedEndpoint() // endpoint = ModelScoring::getARequestedEndpoint()
} // }
query predicate endpointScores = ModelScoring::endpointScores/3; // query predicate endpointScores = ModelScoring::endpointScores/3;
query predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) { // query predicate shouldResultBeIncluded(DataFlow::Node source, DataFlow::Node sink) {
any(ScoringResults scoringResults).shouldResultBeIncluded(source, sink) and // any(ScoringResults scoringResults).shouldResultBeIncluded(source, sink) and
any(DataFlow::Configuration cfg).hasFlow(source, sink) // 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. * 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 * @kind path-problem
* @scored * @scored
* @problem.severity error * @problem.severity error
* @security-severity 8.8 * @security-severity 8.8
* @id js/ml-powered/sql-injection * @id js/ml-powered/silliness
* @tags experimental security
* external/cwe/cwe-089
*/ */
import javascript
import experimental.adaptivethreatmodeling.SqlInjectionATM import experimental.adaptivethreatmodeling.SqlInjectionATM
import experimental.adaptivethreatmodeling.PromptConfiguration
import ATM::ResultsInfo import ATM::ResultsInfo
import DataFlow::PathGraph import DataFlow::PathGraph