A while ago, I had the urge to get a free T-shirt from the Dutch NCSC (National Cyber Security Center). They have a responsible disclosure program, where if you submit a vulnerability which is in their scope, you get a free T-shirt.
My hunt started at this GitHub gist. It contains a script that obtains all domains in scope of their program, and outputs it to a text file. After browsing the sites for a while, I found antenneregister.nl, which is a site that maps all antennas placed in the Netherlands. I put the application through BurpSuite, and it seemed to make use of ArcGIS, which is software that allows you to build maps. I found an interesting request:
GET /arcgis/rest/services/Antenneregister/Zoek_extern/MapServer/0/query?f=json&where=LOWER%28GEMEENTENAAM%29%20LIKE%20%27%25d%25%27&returnGeometry=true&spatialRel=esriSpatialRelIntersects&outFields=&outSR=28992 HTTP/1.1
Accept: */*
Accept-Language: en-US
origin: https://antenneregister.nl
priority: u=1, i
--snip--
Referer: https://antenneregister.nl/Html5Viewer/Index.html?viewer=Antenneregister_extern
Host: gisextern.dictu.nl
Accept-Encoding: gzip, deflate, br
Connection: close
An HTTP request that contains a where
parameter whose value (URL decoded: LOWER(GEMEENTENAAM) LIKE '%d%'
) looks like plain SQL? This seemed to be a perfect candidate for an SQL injection.
After trying a number of payloads, I found that this application is vulnerable to time-based blind SQL injection, which has already been fixed by the vendor.
For example, if we send the above request with where
parameter (URL decoded):
LOWER(GEMEENTENAAM) LIKE '%d%' AND ASCII(SUBSTRC((SELECT CASE WHEN (1=1) THEN 'a'||dbms_pipe.receive_message(('a'),100) ELSE NULL END FROM dual),6,1))>0
We were able to make the application sleep for 100 seconds. Bingo! This happens because 1=1
always equals TRUE
, therefore the THEN
part of this SQL statement is executed, which makes use of dbms_pipe.receive_message
, a database function that allows for a timeout. Now, if attackers constructed specific queries in the 1=1
part, they would have been able to infer the contents of the database based on the time it takes to retrieve a response from the backend.
I hope you learned something, and that I intrigued you to start hunting as well. Until next time!
- Pim