@@ -1032,6 +1032,205 @@ private module Stdlib {
10321032
10331033 override string getFormat ( ) { result = "JSON" }
10341034 }
1035+
1036+ // ---------------------------------------------------------------------------
1037+ // cgi
1038+ // ---------------------------------------------------------------------------
1039+ /** Gets a reference to the `cgi` module. */
1040+ private DataFlow:: Node cgi ( DataFlow:: TypeTracker t ) {
1041+ t .start ( ) and
1042+ result = DataFlow:: importNode ( "cgi" )
1043+ or
1044+ exists ( DataFlow:: TypeTracker t2 | result = cgi ( t2 ) .track ( t2 , t ) )
1045+ }
1046+
1047+ /** Gets a reference to the `cgi` module. */
1048+ DataFlow:: Node cgi ( ) { result = cgi ( DataFlow:: TypeTracker:: end ( ) ) }
1049+
1050+ /** Provides models for the `cgi` module. */
1051+ module cgi {
1052+ /**
1053+ * Provides models for the `cgi.FieldStorage` class
1054+ *
1055+ * See https://docs.python.org/3/library/cgi.html.
1056+ */
1057+ module FieldStorage {
1058+ /** Gets a reference to the `cgi.FieldStorage` class. */
1059+ private DataFlow:: Node classRef ( DataFlow:: TypeTracker t ) {
1060+ t .startInAttr ( "FieldStorage" ) and
1061+ result = cgi ( )
1062+ or
1063+ exists ( DataFlow:: TypeTracker t2 | result = classRef ( t2 ) .track ( t2 , t ) )
1064+ }
1065+
1066+ /** Gets a reference to the `cgi.FieldStorage` class. */
1067+ DataFlow:: Node classRef ( ) { result = classRef ( DataFlow:: TypeTracker:: end ( ) ) }
1068+
1069+ /**
1070+ * A source of an instance of `cgi.FieldStorage`.
1071+ *
1072+ * This can include instantiation of the class, return value from function
1073+ * calls, or a special parameter that will be set when functions are call by external
1074+ * library.
1075+ *
1076+ * Use `FieldStorage::instance()` predicate to get references to instances of `cgi.FieldStorage`.
1077+ */
1078+ abstract class InstanceSource extends DataFlow:: Node { }
1079+
1080+ /**
1081+ * A direct instantiation of `cgi.FieldStorage`.
1082+ *
1083+ * We currently consider ALL instantiations to be `RemoteFlowSource`. This seems
1084+ * reasonable since it's used to parse form data for incoming POST requests, but
1085+ * if it turns out to be a problem, we'll have to refine.
1086+ */
1087+ private class ClassInstantiation extends InstanceSource , RemoteFlowSource:: Range ,
1088+ DataFlow:: CfgNode {
1089+ override CallNode node ;
1090+
1091+ ClassInstantiation ( ) { node .getFunction ( ) = classRef ( ) .asCfgNode ( ) }
1092+
1093+ override string getSourceType ( ) { result = "cgi.FieldStorage" }
1094+ }
1095+
1096+ /** Gets a reference to an instance of `cgi.FieldStorage`. */
1097+ private DataFlow:: Node instance ( DataFlow:: TypeTracker t ) {
1098+ t .start ( ) and
1099+ result instanceof InstanceSource
1100+ or
1101+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
1102+ }
1103+
1104+ /** Gets a reference to an instance of `cgi.FieldStorage`. */
1105+ DataFlow:: Node instance ( ) { result = instance ( DataFlow:: TypeTracker:: end ( ) ) }
1106+
1107+ /** Gets a reference to the `getvalue` method on a `cgi.FieldStorage` instance. */
1108+ private DataFlow:: Node getvalueRef ( DataFlow:: TypeTracker t ) {
1109+ t .startInAttr ( "getvalue" ) and
1110+ result = instance ( )
1111+ or
1112+ exists ( DataFlow:: TypeTracker t2 | result = getvalueRef ( t2 ) .track ( t2 , t ) )
1113+ }
1114+
1115+ /** Gets a reference to the `getvalue` method on a `cgi.FieldStorage` instance. */
1116+ DataFlow:: Node getvalueRef ( ) { result = getvalueRef ( DataFlow:: TypeTracker:: end ( ) ) }
1117+
1118+ /** Gets a reference to the result of calling the `getvalue` method on a `cgi.FieldStorage` instance. */
1119+ private DataFlow:: Node getvalueResult ( DataFlow:: TypeTracker t ) {
1120+ t .start ( ) and
1121+ result .asCfgNode ( ) .( CallNode ) .getFunction ( ) = getvalueRef ( ) .asCfgNode ( )
1122+ or
1123+ exists ( DataFlow:: TypeTracker t2 | result = getvalueResult ( t2 ) .track ( t2 , t ) )
1124+ }
1125+
1126+ /** Gets a reference to the result of calling the `getvalue` method on a `cgi.FieldStorage` instance. */
1127+ DataFlow:: Node getvalueResult ( ) { result = getvalueResult ( DataFlow:: TypeTracker:: end ( ) ) }
1128+
1129+ /** Gets a reference to the `getfirst` method on a `cgi.FieldStorage` instance. */
1130+ private DataFlow:: Node getfirstRef ( DataFlow:: TypeTracker t ) {
1131+ t .startInAttr ( "getfirst" ) and
1132+ result = instance ( )
1133+ or
1134+ exists ( DataFlow:: TypeTracker t2 | result = getfirstRef ( t2 ) .track ( t2 , t ) )
1135+ }
1136+
1137+ /** Gets a reference to the `getfirst` method on a `cgi.FieldStorage` instance. */
1138+ DataFlow:: Node getfirstRef ( ) { result = getfirstRef ( DataFlow:: TypeTracker:: end ( ) ) }
1139+
1140+ /** Gets a reference to the result of calling the `getfirst` method on a `cgi.FieldStorage` instance. */
1141+ private DataFlow:: Node getfirstResult ( DataFlow:: TypeTracker t ) {
1142+ t .start ( ) and
1143+ result .asCfgNode ( ) .( CallNode ) .getFunction ( ) = getfirstRef ( ) .asCfgNode ( )
1144+ or
1145+ exists ( DataFlow:: TypeTracker t2 | result = getfirstResult ( t2 ) .track ( t2 , t ) )
1146+ }
1147+
1148+ /** Gets a reference to the result of calling the `getfirst` method on a `cgi.FieldStorage` instance. */
1149+ DataFlow:: Node getfirstResult ( ) { result = getfirstResult ( DataFlow:: TypeTracker:: end ( ) ) }
1150+
1151+ /** Gets a reference to the `getlist` method on a `cgi.FieldStorage` instance. */
1152+ private DataFlow:: Node getlistRef ( DataFlow:: TypeTracker t ) {
1153+ t .startInAttr ( "getlist" ) and
1154+ result = instance ( )
1155+ or
1156+ exists ( DataFlow:: TypeTracker t2 | result = getlistRef ( t2 ) .track ( t2 , t ) )
1157+ }
1158+
1159+ /** Gets a reference to the `getlist` method on a `cgi.FieldStorage` instance. */
1160+ DataFlow:: Node getlistRef ( ) { result = getlistRef ( DataFlow:: TypeTracker:: end ( ) ) }
1161+
1162+ /** Gets a reference to the result of calling the `getlist` method on a `cgi.FieldStorage` instance. */
1163+ private DataFlow:: Node getlistResult ( DataFlow:: TypeTracker t ) {
1164+ t .start ( ) and
1165+ result .asCfgNode ( ) .( CallNode ) .getFunction ( ) = getlistRef ( ) .asCfgNode ( )
1166+ or
1167+ exists ( DataFlow:: TypeTracker t2 | result = getlistResult ( t2 ) .track ( t2 , t ) )
1168+ }
1169+
1170+ /** Gets a reference to the result of calling the `getlist` method on a `cgi.FieldStorage` instance. */
1171+ DataFlow:: Node getlistResult ( ) { result = getlistResult ( DataFlow:: TypeTracker:: end ( ) ) }
1172+
1173+ /** Gets a reference to a list of fields. */
1174+ private DataFlow:: Node fieldList ( DataFlow:: TypeTracker t ) {
1175+ t .start ( ) and
1176+ (
1177+ result = getlistResult ( )
1178+ or
1179+ result = getvalueResult ( )
1180+ or
1181+ // TODO: Should have better handling of subscripting
1182+ result .asCfgNode ( ) .( SubscriptNode ) .getObject ( ) = instance ( ) .asCfgNode ( )
1183+ )
1184+ or
1185+ exists ( DataFlow:: TypeTracker t2 | result = fieldList ( t2 ) .track ( t2 , t ) )
1186+ }
1187+
1188+ /** Gets a reference to a list of fields. */
1189+ DataFlow:: Node fieldList ( ) { result = fieldList ( DataFlow:: TypeTracker:: end ( ) ) }
1190+
1191+ /** Gets a reference to a field. */
1192+ private DataFlow:: Node field ( DataFlow:: TypeTracker t ) {
1193+ t .start ( ) and
1194+ (
1195+ result = getfirstResult ( )
1196+ or
1197+ result = getvalueResult ( )
1198+ or
1199+ // TODO: Should have better handling of subscripting
1200+ result .asCfgNode ( ) .( SubscriptNode ) .getObject ( ) = [ instance ( ) , fieldList ( ) ] .asCfgNode ( )
1201+ )
1202+ or
1203+ exists ( DataFlow:: TypeTracker t2 | result = field ( t2 ) .track ( t2 , t ) )
1204+ }
1205+
1206+ /** Gets a reference to a field. */
1207+ DataFlow:: Node field ( ) { result = field ( DataFlow:: TypeTracker:: end ( ) ) }
1208+
1209+ private class AdditionalTaintStep extends TaintTracking:: AdditionalTaintStep {
1210+ override predicate step ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo ) {
1211+ // Methods
1212+ nodeFrom = instance ( ) and
1213+ nodeTo in [ getvalueRef ( ) , getfirstRef ( ) , getlistRef ( ) ]
1214+ or
1215+ nodeFrom = getvalueRef ( ) and nodeTo = getvalueResult ( )
1216+ or
1217+ nodeFrom = getfirstRef ( ) and nodeTo = getfirstResult ( )
1218+ or
1219+ nodeFrom = getlistRef ( ) and nodeTo = getlistResult ( )
1220+ or
1221+ // Indexing
1222+ nodeFrom in [ instance ( ) , fieldList ( ) ] and
1223+ nodeTo .asCfgNode ( ) .( SubscriptNode ) .getObject ( ) = nodeFrom .asCfgNode ( )
1224+ or
1225+ // Attributes on Field
1226+ nodeFrom = field ( ) and
1227+ exists ( DataFlow:: AttrRead read | nodeTo = read and read .getObject ( ) = nodeFrom |
1228+ read .getAttributeName ( ) in [ "value" , "file" , "filename" ]
1229+ )
1230+ }
1231+ }
1232+ }
1233+ }
10351234}
10361235
10371236// ---------------------------------------------------------------------------
0 commit comments