@@ -129,7 +129,11 @@ def setUp(self):
129129 "inj" : (kb .injection .place , kb .injection .parameter , kb .injection .data ),
130130 "qp" : Connect .queryPage ,
131131 "dbmsHandler" : conf .get ("dbmsHandler" ), "forceDbms" : conf .get ("forceDbms" ),
132+ "charsStart" : kb .chars .start , "charsStop" : kb .chars .stop ,
132133 }
134+ # Pin the boundary markers so the CAP-relative channel capacity is deterministic and the
135+ # extraction regex can never hit a leaked/odd marker (the default markers are random).
136+ kb .chars .start , kb .chars .stop = "qzxjq" , "qkvbq"
133137 conf .hexConvert = False
134138 conf .charset = None
135139 conf .hashDB = None
@@ -165,12 +169,17 @@ def tearDown(self):
165169 eu .Request .queryPage = self ._saved ["qp" ]
166170 conf .dbmsHandler = self ._saved ["dbmsHandler" ]
167171 conf .forceDbms = self ._saved ["forceDbms" ]
172+ kb .chars .start = self ._saved ["charsStart" ]
173+ kb .chars .stop = self ._saved ["charsStop" ]
168174
169175 def _install_oracle (self , secret = "hello" ):
170176 cap = self .CAP
171177
172178 def oracle (payload = None , content = False , raise404 = True , ** kwargs ):
173- m = re .search (r"REPEAT\((?:0x([0-9a-fA-F]{2})|'(.)'),(\d+)\)" , payload ) # chunk-length probe
179+ # chunk-length probe: recognize every repeat-family builder the search may emit
180+ # (REPEAT=MySQL, REPLICATE=MSSQL/Sybase, RPAD=Oracle/Firebird) so a leaked non-MySQL
181+ # back-end still exercises the search instead of mis-detecting length 0
182+ m = re .search (r"(?:REPEAT|REPLICATE|RPAD)\((?:0x([0-9a-fA-F]{2})|'(.)'),(\d+)" , payload )
174183 if m :
175184 raw = (chr (int (m .group (1 ), 16 )) if m .group (1 ) else m .group (2 )) * int (m .group (3 ))
176185 else :
0 commit comments