@@ -2146,3 +2146,156 @@ async def test_filter_event(self, module_test):
21462146 def check (self , module_test , events ):
21472147 # This test doesn't need to check events since it's testing the filter method directly
21482148 pass
2149+
2150+
2151+ # try_post_as_get: fuzz POST parameters as GET parameters
2152+ class Test_Lightfuzz_try_post_as_get (ModuleTestBase ):
2153+ targets = ["http://127.0.0.1:8888" ]
2154+ modules_overrides = ["httpx" , "lightfuzz" , "excavate" ]
2155+ config_overrides = {
2156+ "interactsh_disable" : True ,
2157+ "modules" : {
2158+ "lightfuzz" : {
2159+ "enabled_submodules" : ["sqli" ],
2160+ "disable_post" : True ,
2161+ "try_post_as_get" : True ,
2162+ }
2163+ },
2164+ }
2165+
2166+ def request_handler (self , request ):
2167+ qs = str (request .query_string .decode ())
2168+
2169+ parameter_block = """
2170+ <section class=search>
2171+ <form action=/ method=POST>
2172+ <input type=text placeholder='Search the blog...' name=search>
2173+ <button type=submit class=button>Search</button>
2174+ </form>
2175+ </section>
2176+ """
2177+
2178+ if "search=" in qs :
2179+ value = qs .split ("=" )[1 ]
2180+ if "&" in value :
2181+ value = value .split ("&" )[0 ]
2182+
2183+ sql_block_normal = f"""
2184+ <section class=blog-header>
2185+ <h1>0 search results for '{ unquote (value )} '</h1>
2186+ <hr>
2187+ </section>
2188+ """
2189+
2190+ sql_block_error = """
2191+ <section class=error>
2192+ <h1>Found error in SQL query</h1>
2193+ <hr>
2194+ </section>
2195+ """
2196+ if value .endswith ("'" ):
2197+ if value .endswith ("''" ):
2198+ return Response (sql_block_normal , status = 200 )
2199+ return Response (sql_block_error , status = 500 )
2200+ return Response (parameter_block , status = 200 )
2201+
2202+ async def setup_after_prep (self , module_test ):
2203+ module_test .scan .modules ["lightfuzz" ].helpers .rand_string = lambda * args , ** kwargs : "AAAAAAAAAAAAAA"
2204+ expect_args = re .compile ("/" )
2205+ module_test .set_expect_requests_handler (expect_args = expect_args , request_handler = self .request_handler )
2206+
2207+ def check (self , module_test , events ):
2208+ web_parameter_emitted = False
2209+ sqli_getparam_finding_emitted = False
2210+ sqli_postparam_finding_emitted = False
2211+ for e in events :
2212+ if e .type == "WEB_PARAMETER" :
2213+ if "HTTP Extracted Parameter [search]" in e .data ["description" ]:
2214+ web_parameter_emitted = True
2215+
2216+ if e .type == "FINDING" :
2217+ if (
2218+ "Possible SQL Injection. Parameter: [search] Parameter Type: [GETPARAM] (converted from POSTPARAM) Detection Method: [Single Quote/Two Single Quote, Code Change (200->500->200)]"
2219+ in e .data ["description" ]
2220+ ):
2221+ sqli_getparam_finding_emitted = True
2222+ if "Possible SQL Injection. Parameter: [search] Parameter Type: [POSTPARAM]" in e .data ["description" ]:
2223+ sqli_postparam_finding_emitted = True
2224+
2225+ assert web_parameter_emitted , "WEB_PARAMETER was not emitted"
2226+ assert sqli_getparam_finding_emitted , (
2227+ "SQLi GETPARAM (converted from POSTPARAM) FINDING not emitted (try_post_as_get failed)"
2228+ )
2229+ assert not sqli_postparam_finding_emitted , "POSTPARAM FINDING emitted despite disable_post=True"
2230+
2231+
2232+ # try_get_as_post: fuzz GET parameters as POST parameters
2233+ class Test_Lightfuzz_try_get_as_post (ModuleTestBase ):
2234+ targets = ["http://127.0.0.1:8888" ]
2235+ modules_overrides = ["httpx" , "lightfuzz" , "excavate" ]
2236+ config_overrides = {
2237+ "interactsh_disable" : True ,
2238+ "modules" : {
2239+ "lightfuzz" : {
2240+ "enabled_submodules" : ["sqli" ],
2241+ "try_get_as_post" : True ,
2242+ }
2243+ },
2244+ }
2245+
2246+ def request_handler (self , request ):
2247+ parameter_block = """
2248+ <section class=search>
2249+ <form action=/ method=GET>
2250+ <input type=text placeholder='Search the blog...' name=search>
2251+ <button type=submit class=button>Search</button>
2252+ </form>
2253+ </section>
2254+ """
2255+
2256+ if request .method == "POST" and "search" in request .form .keys ():
2257+ value = request .form ["search" ]
2258+
2259+ sql_block_normal = f"""
2260+ <section class=blog-header>
2261+ <h1>0 search results for '{ unquote (value )} '</h1>
2262+ <hr>
2263+ </section>
2264+ """
2265+
2266+ sql_block_error = """
2267+ <section class=error>
2268+ <h1>Found error in SQL query</h1>
2269+ <hr>
2270+ </section>
2271+ """
2272+ if value .endswith ("'" ):
2273+ if value .endswith ("''" ):
2274+ return Response (sql_block_normal , status = 200 )
2275+ return Response (sql_block_error , status = 500 )
2276+ return Response (parameter_block , status = 200 )
2277+
2278+ async def setup_after_prep (self , module_test ):
2279+ module_test .scan .modules ["lightfuzz" ].helpers .rand_string = lambda * args , ** kwargs : "AAAAAAAAAAAAAA"
2280+ expect_args = re .compile ("/" )
2281+ module_test .set_expect_requests_handler (expect_args = expect_args , request_handler = self .request_handler )
2282+
2283+ def check (self , module_test , events ):
2284+ web_parameter_emitted = False
2285+ sqli_postparam_converted_finding_emitted = False
2286+ for e in events :
2287+ if e .type == "WEB_PARAMETER" :
2288+ if "HTTP Extracted Parameter [search]" in e .data ["description" ]:
2289+ web_parameter_emitted = True
2290+
2291+ if e .type == "FINDING" :
2292+ if (
2293+ "Possible SQL Injection. Parameter: [search] Parameter Type: [POSTPARAM] (converted from GETPARAM) Detection Method: [Single Quote/Two Single Quote, Code Change (200->500->200)]"
2294+ in e .data ["description" ]
2295+ ):
2296+ sqli_postparam_converted_finding_emitted = True
2297+
2298+ assert web_parameter_emitted , "WEB_PARAMETER was not emitted"
2299+ assert sqli_postparam_converted_finding_emitted , (
2300+ "SQLi POSTPARAM (converted from GETPARAM) FINDING not emitted (try_get_as_post failed)"
2301+ )
0 commit comments