Nov 4, 2022
SQLmap; Customizing tools to get the job done
Often we run into a false-positive SQLi (SQL injection) using SQLmap. Even then, our team will attempt to dig deeper and sometimes we hit roadblocks. By working on client’s project and faced the exact challenge. After careful enumeration and testing, an entry point was found that was vulnerable to SQLi.
During this engagement, application responses hinted at the presence of a Time-Based SQLi vulnerability, but results were inconsistent and common tools failed to validate the issue. It took some manual tweaking, trial and error to get the correct responses. SQLmap didn’t work by default and therefore, we wrote a simple script of our own to do some of the manual tasks and speedup the process.
In the example image below is a python script which retrieved the hostname of the server. The idea behind this is to get the correct data out based on two factors, one which is the response time and two is the size of the response. Knowing that, it gave us an idea how the server responses and with the script working we knew the vulnerability was real. Custom python SQL script as a PoC.
Due to the complexity of the scripts, SQL payloads and a limitation the remaining time of the engagement wasn’t in our favor. A better approach is to look into the SQLmap tool and try make it work.
Once we could prove the injection existed with True and False behavior it was time to make our tools work for us. In this case we examined the false-positive results from SQLmap to determine why the tool was giving us a false-negative. A neat trick for this sort of analysis is to proxy SQLmap through Burp Suite and watch the traffic. Doing exactly this led us to observe the behavior triggering the false-negative in SQLmap. How could we convince SQLmap that our injection was real? By dissecting the code, we were able to short-circuit the false-positive detection logic.
By simply ensuring the false-positive function returned the proper value (True) we could convince SQLmap to keep on keeping on. With our slight modification in place and using a custom injection point inside our manually developed payload, we were able to make SQLmap do the heavy lifting and extract all the goodness from the database. checks.py in the SQLmap script was modified to return the value. retVal is set to True in our case.