11/**
2- * Provides a taint-tracking configuration for reasoning about cross-site
3- * scripting vulnerabilities where the taint-flow passes through a thrown
4- * exception.
2+ * Provides a taint-tracking configuration for reasoning about cross-site
3+ * scripting vulnerabilities where the taint-flow passes through a thrown
4+ * exception.
55 */
66
77import javascript
88
99module ExceptionXss {
1010 import DomBasedXssCustomizations:: DomBasedXss as DomBasedXssCustom
11- import ReflectedXssCustomizations:: ReflectedXss as ReflectedXssCustom
12- import Xss:: DomBasedXss as DomBasedXss
11+ import ReflectedXssCustomizations:: ReflectedXss as ReflectedXssCustom
12+ import Xss:: DomBasedXss as DomBasedXss
1313 import Xss:: ReflectedXss as ReflectedXSS
1414 import Xss:: StoredXss as StoredXss
1515 import Xss as XSS
1616
1717 DataFlow:: ExceptionalInvocationReturnNode getCallerExceptionalReturn ( Function func ) {
1818 exists ( DataFlow:: InvokeNode call |
1919 not call .isImprecise ( ) and
20- func = call .getACallee ( ) and
20+ func = call .getACallee ( 0 ) and
2121 result = call .getExceptionalReturn ( )
2222 )
2323 }
2424
2525 DataFlow:: Node getExceptionalSuccessor ( DataFlow:: Node pred ) {
26- if exists ( getEnclosingTryStmt ( pred .asExpr ( ) .getEnclosingStmt ( ) ) )
26+ if exists ( pred .asExpr ( ) .getEnclosingStmt ( ) . getEnclosingTryStmt ( ) )
2727 then
28- result = DataFlow:: parameterNode ( getEnclosingTryStmt ( pred
28+ result = DataFlow:: parameterNode ( pred
2929 .asExpr ( )
30- .getEnclosingStmt ( ) ) .getACatchClause ( ) .getAParameter ( ) )
30+ .getEnclosingStmt ( )
31+ .getEnclosingTryStmt ( )
32+ .getACatchClause ( )
33+ .getAParameter ( ) )
3134 else result = getCallerExceptionalReturn ( pred .getContainer ( ) )
3235 }
3336
@@ -38,54 +41,51 @@ module ExceptionXss {
3841 node .asExpr ( ) .getEnclosingStmt ( ) instanceof ThrowStmt
3942 }
4043
41- TryStmt getEnclosingTryStmt ( Stmt stmt ) {
42- stmt .getParentStmt + ( ) = result .getBody ( ) and
43- not exists ( TryStmt mid |
44- stmt .getParentStmt + ( ) = mid .getBody ( ) and mid .getParentStmt + ( ) = result .getBody ( )
45- )
46- }
47-
4844 /**
49- * A FlowLabel representing tainted data that has not been thrown in an exception.
45+ * A FlowLabel representing tainted data that has not been thrown in an exception.
5046 * In the js/xss-through-exception query data-flow can only reach a sink after
51- * the data has been thrown as an exception, and data that has not been thrown
52- * as an exception therefore has this flow label, and only this flow label, associated with it.
47+ * the data has been thrown as an exception, and data that has not been thrown
48+ * as an exception therefore has this flow label, and only this flow label, associated with it.
5349 */
5450 class NotYetThrown extends DataFlow:: FlowLabel {
5551 NotYetThrown ( ) { this = "NotYetThrown" }
5652 }
5753
5854 /**
59- * A taint-tracking configuration for reasoning about XSS with possible exceptional flow.
60- * Flow labels are used to ensure that we only report taint-flow that has been thrown in
61- * an exception.
55+ * A taint-tracking configuration for reasoning about XSS with possible exceptional flow.
56+ * Flow labels are used to ensure that we only report taint-flow that has been thrown in
57+ * an exception.
6258 */
6359 class Configuration extends TaintTracking:: Configuration {
64- Configuration ( ) { this = "ExceptionXss" }
60+ Configuration ( ) { this = "ExceptionXss" }
6561
6662 override predicate isSource ( DataFlow:: Node source , DataFlow:: FlowLabel label ) {
6763 source instanceof XSS:: Shared:: Source and label instanceof NotYetThrown
6864 }
69-
65+
7066 override predicate isSink ( DataFlow:: Node sink , DataFlow:: FlowLabel label ) {
7167 sink instanceof XSS:: Shared:: Sink and not label instanceof NotYetThrown
7268 }
7369
74- override predicate isSanitizer ( DataFlow:: Node node ) {
75- node instanceof XSS:: Shared:: Sanitizer
76- }
70+ override predicate isSanitizer ( DataFlow:: Node node ) { node instanceof XSS:: Shared:: Sanitizer }
7771
78- override predicate isAdditionalFlowStep ( DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel inlbl , DataFlow:: FlowLabel outlbl ) {
79- inlbl instanceof NotYetThrown and ( outlbl .isTaint ( ) or outlbl instanceof NotYetThrown ) and
72+ override predicate isAdditionalFlowStep (
73+ DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel inlbl ,
74+ DataFlow:: FlowLabel outlbl
75+ ) {
76+ inlbl instanceof NotYetThrown and
77+ ( outlbl .isTaint ( ) or outlbl instanceof NotYetThrown ) and
8078 succ = getExceptionalSuccessor ( pred ) and
81- ( canThrowSensitiveInformation ( pred ) or pred = any ( DataFlow:: InvokeNode c ) .getExceptionalReturn ( ) )
79+ (
80+ canThrowSensitiveInformation ( pred ) or
81+ pred = any ( DataFlow:: InvokeNode c ) .getExceptionalReturn ( )
82+ )
8283 or
8384 // All the usual taint-flow steps apply on data-flow before it has been thrown in an exception.
84- this .isAdditionalFlowStep ( pred , succ ) and inlbl instanceof NotYetThrown and outlbl instanceof NotYetThrown
85+ this .isAdditionalFlowStep ( pred , succ ) and inlbl instanceof NotYetThrown and outlbl instanceof NotYetThrown
8586 or
86- // We taint an object deep if it happens before an exception has been thrown.
87- inlbl instanceof NotYetThrown and outlbl instanceof NotYetThrown and
88- exists ( DataFlow:: PropWrite write | write .getRhs ( ) = pred and write .getBase ( ) = succ )
87+ // We taint an object deep if it happens before an exception has been thrown.
88+ inlbl instanceof NotYetThrown and outlbl instanceof NotYetThrown and exists ( DataFlow:: PropWrite write | write .getRhs ( ) = pred and write .getBase ( ) = succ )
8989 }
9090 }
9191}
0 commit comments