Site has been hacked via SQL Injection
Recently my site was hacked via SQL injection. The hacker used the following query to get my DB name. I cannot understand this query they wrote.
Query:
=-999.9%20UNION%20ALL%20SELECT%20concat(0x7e,0x27,Hex(cast(database()%20as%20char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235开发者_如何学Go343830303536--
After the query was ran it showed an integer result, something like "74545883
".
Can you explain how the query works?
It looks like an overflow attack. They UNION
-ed with your existing query. replacing all your %20
with (space) since its url-encoded yields:
=-999.9 UNION ALL SELECT CONCAT(0x7e,0x27,Hex(cast(database() as char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235343830303536-
break it down:
- the
=-999.9
is just ending your current query 0x31303235343830303536
isNULL
- they are just matching the number of columns in your existing query. If you hadSELECT * FROM users
andusers
had 4 columns, theUNION
must also have 4 columns. As a result, they just used `NULL values to populate those columns.- the real confusion is in the
CONCAT()
. They are combining 126, 39, database name as hex value, 39, and 126 --
is a mysql comment - it ignores the rest of your query after
Judging from this attack, i suspect that you are not wrapping input in mysql_real_escape_string()
, which allowed to attacked to jump out of your query and execute their own.
See owasp.org for more information.
This is not the complete query, actually the person entered this string in your web app.
Now, first replace %20 with blank space in the union part, you get:
SELECT concat(0x7e,0x27,Hex(cast(database() as char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235343830303536--
Seems like the user put the string in some place where you were expecting an number. So, you see that first there is a number (999.9) to complete the original condition of the query. Then, an UNION part is added. Finally, after the UNION part, the comment characters are added (-- ) so that, the rest of the query (which might be being added by your system) is bypassed.
We can format the code for better understanding:
SELECT
concat
(
0x7e,
0x27,
Hex(cast(database() as char)),
0x27,
0x7e
),
0x31303235343830303536,
0x31303235343830303536,
0x31303235343830303536
Now, substring of the first column of the result will contain the hex encoded form of your datbase name. Actually, it should be surrounded by single quotes (0x27), then again surrounded by ~ (0x7e)
The query returned the Database name using DATABASE() , it then converted this to a hex value using HEx() function.
Once they had this they could use UNHEX function
Have a look at the UNHEX
examples
mysql> SELECT UNHEX('4D7953514C');
-> 'MySQL'
mysql> SELECT 0x4D7953514C;
-> 'MySQL'
mysql> SELECT UNHEX(HEX('string'));
-> 'string'
mysql> SELECT HEX(UNHEX('1267'));
-> '1267'
It is good to know how they got in, but all in all, you need to fix up your code to avoid SQL Injection.
-999.9 UNION ALL SELECT
CONCAT('Hex(cast(database() as char))'),
0x31303235343830303536,
0x31303235343830303536,
0x31303235343830303536
I think you must have other entries in your log, if not he knew before hand that you have 3 columns.
This is an exemple of injection using Havij
The 0x7e and 0x27 correspond to ~ and ' wich will be used to frame the HTML display
such as
id=999999.9+union+all+select+0x31303235343830303536,(select+concat(0x7e,0x27,unhex(Hex(cast(sample_tbl.name+as+char))),0x27,0x7e)+from+test
.sample_tbl+Order+by+id+limit+0,1)+--
This query will render ~'Alfred'~ which is the field value of the column name, from the table sample_tbl in the table test
~'r3dm0v3_hvj_injection'~ is the Havij signature code unhex 0x7233646D3076335F68766A5F696E6A656374696F6E according to http://www.string-functions.com/hex-string.aspx
First off, the query looks like it's HTML encoded. Replace the %20
s with spaces and it will become a little more readable. Also they are converting part of the query into a hex representation of something. Try hexadecimal decoding that part of the statement as well.
A SQL injection risk is created when you try to create a SQL dynamically as a string, and then send it to the DBMS. Imagine a string like this stored in your system for use in a search bar, etc:
SELECT * FROM SOME_TABLE WHERE SOME_COLUMN=
To complete the query and let the attack in, they would need to make their input like this:
'x' or 1=1
In that instance the query will become:
SELECT * FROM SOME_TABLE WHERE SOME_COLUMN='x' or 1=1
SOME_COLUMN
could be any variable, it doesn't matter where it fails, the thing that matters is that 1=1
is ALWAYS true, thereby potentially giving the attacker access to every row in that table.
Now that you know about it, go through your code and replace every dynamically created query with a Prepared Statements. The OWASP site has a lot of resources for defensive coding as well:
www.owasp.org
Yes he has got the hex form of your database name which you say is '74545883'. By Unhexing it he would have got the real database name.
精彩评论