@@ -49,6 +49,9 @@ class TarfileOpen extends TaintSource {
4949 * this tarfile is safe.
5050 */
5151 not this .( CallNode ) .getAnArg ( ) .refersTo ( any ( StringObject str ) )
52+ and
53+ /* Ignore opens within the tarfile module itself */
54+ not this .( ControlFlowNode ) .getLocation ( ) .getFile ( ) .getBaseName ( ) = "tarfile.py"
5255 }
5356
5457 override predicate isSourceOf ( TaintKind kind ) {
@@ -73,13 +76,33 @@ class TarFileInfo extends TaintKind {
7376}
7477
7578
79+ /* For efficiency we don't want to track the flow of taint
80+ * around the tarfile module. */
81+ class ExcludeTarFilePy extends Sanitizer {
82+
83+ ExcludeTarFilePy ( ) {
84+ this = "Tar sanitizer"
85+ }
86+
87+ override predicate sanitizingNode ( TaintKind taint , ControlFlowNode node ) {
88+ node .getLocation ( ) .getFile ( ) .getBaseName ( ) = "tarfile.py" and
89+ (
90+ taint instanceof OpenTarFile
91+ or
92+ taint instanceof TarFileInfo
93+ )
94+ }
95+
96+ }
97+
7698/* Any call to an extractall method */
7799class ExtractAllSink extends TaintSink {
78100
79101 CallNode call ;
80102
81103 ExtractAllSink ( ) {
82- this = call .getFunction ( ) .( AttrNode ) .getObject ( "extractall" )
104+ this = call .getFunction ( ) .( AttrNode ) .getObject ( "extractall" ) and
105+ count ( call .getAnArg ( ) ) = 0
83106 }
84107
85108 override predicate sinks ( TaintKind kind ) {
@@ -104,6 +127,25 @@ class ExtractSink extends TaintSink {
104127
105128}
106129
130+
131+ /* Members argument to extract method */
132+ class ExtractMembersSink extends TaintSink {
133+
134+ CallNode call ;
135+
136+ ExtractMembersSink ( ) {
137+ call .getFunction ( ) .( AttrNode ) .getName ( ) = "extractall" and
138+ ( this = call .getArg ( 0 ) or this = call .getArgByName ( "members" ) )
139+ }
140+
141+ override predicate sinks ( TaintKind kind ) {
142+ kind .( SequenceKind ) .getItem ( ) instanceof TarFileInfo
143+ or
144+ kind instanceof OpenTarFile
145+ }
146+
147+ }
148+
107149class TarFileInfoSanitizer extends Sanitizer {
108150
109151 TarFileInfoSanitizer ( ) {
@@ -114,38 +156,39 @@ class TarFileInfoSanitizer extends Sanitizer {
114156 path_sanitizing_test ( test .getTest ( ) ) and
115157 taint instanceof TarFileInfo
116158 }
117- }
118159
119- private predicate path_sanitizing_test ( ControlFlowNode test ) {
120- checks_not_absolute ( test ) and
121- test .getAChild + ( ) .getNode ( ) .( StrConst ) .getText ( ) = ".."
160+
122161}
123162
124- private predicate checks_not_absolute ( ControlFlowNode test ) {
125- test .getAChild + ( ) .( CallNode ) .getFunction ( ) .pointsTo ( Module:: named ( "os.path" ) .attr ( "absfile" ) )
163+ private predicate path_sanitizing_test ( ControlFlowNode test ) {
164+ /* Assume that any test with "path" in it is a sanitizer */
165+ test .getAChild + ( ) .( AttrNode ) .getName ( ) = "path"
126166 or
127- test .getAChild + ( ) .getNode ( ) . ( StrConst ) . getText ( ) = "/ "
167+ test .getAChild + ( ) .( NameNode ) . getId ( ) = "path "
128168}
129169
130-
131170class TarSlipConfiguration extends TaintTracking:: Configuration {
132171
133172 TarSlipConfiguration ( ) { this = "TarSlip configuration" }
134173
135174 override predicate isSource ( TaintTracking:: Source source ) { source instanceof TarfileOpen }
136175
137- override predicate isSink ( TaintTracking:: Sink sink ) {
138- sink instanceof ExtractSink or sink instanceof ExtractAllSink
176+ override predicate isSink ( TaintTracking:: Sink sink ) {
177+ sink instanceof ExtractSink or
178+ sink instanceof ExtractAllSink or
179+ sink instanceof ExtractMembersSink
139180 }
140181
141182 override predicate isSanitizer ( Sanitizer sanitizer ) {
142183 sanitizer instanceof TarFileInfoSanitizer
184+ or
185+ sanitizer instanceof ExcludeTarFilePy
143186 }
187+
144188}
145189
146190
147191from TarSlipConfiguration config , TaintedPathSource src , TaintedPathSink sink
148192where config .hasFlowPath ( src , sink )
149193select sink .getSink ( ) , src , sink , "Extraction of tarfile from $@" , src .getSource ( ) , "a potentially untrusted source"
150194
151-
0 commit comments