第四章:Web安全原理剖析
SQL注入
SQL注入就是指web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库查询,攻击者可以通过构造不同的SQL语句来实现对数据库里的任意操作。
SQl注入的原理
SQL漏洞产生两个条件:
参数用户可控:前端传给后端的内容是用户可以控制的
参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询
MySQL注入相关知识
MySQL 5.0版本之后MySQL默认在数据库中存放一个”information_schema“的数据库,该库中三个表名SCHEMATA、TABLES和COLUMNS
SCHEMATA表存储用户创建的所有数据库的库名,记录数据库名的字段为SCHEMA_NAME
TABLES表存储用户创建的所有数据库的库名和表名,数据库字段为TABLE_SCHEMA,表名字段为TABLE_NAME
COLUMNS表存储用户创建的所有数据库的库名、表名、字段名,分别对应的字段TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME
常用查询语句
SELECT 字段名 FROM 库名.表名
SELECT 字段名 FORM 库名.表名 WHERE 已知条件= ‘已知条件的值’ (两条条件中加AND即可)
limit:用法:limit m,n
m代表
几个函数
database():当网站前使用的数据库
version():当前MySQL的版本
user():当前MySQL的用户
注释符
#` 、—— 、 空格 、 `/**/
内联注释:形式/*! code*/
,内联注释 可用于整个SQL语句中,用来执行SQL语句
例子:index.php?id=-15/*! UNION*//*! SELECT*/1,2,3
书上的靶场已经没了,准备用Metasploitable2靶场练习一下。
SQL注入这一部分准备拿出来专门学习一下。
XSS
跨站脚本漏洞,代码输入的一种,允许恶意用户将代码注入网页,在其他用户浏览网页时受到影响,成功后可以得到很高的权限,私密网页内容、会话和cookie等
分类:反射型,存储型,DOM型
原理
反射型:具有一次性,通过电子邮件等方式将包含XSS代码的恶意链接发送给目标用户,被访问时,服务器接收请求并发送带有XSS代码的数据到用户浏览器,浏览器解析后触发XSS漏洞。
存储型:持久,攻击脚本永远存放在目标服务器中,多见于论坛、博客、留言版,将恶意脚本同正常信息一起注入帖子内容中,进而被存入服务器,其他用户访问时在浏览器执行。常见的alert(hello)
DOM型:DOM,可以使程序和脚本能够动态访问和更新文档的内容、结构和央样式。DOM型XSS其实是一种特殊的反射型XSS,基于DOM文档对象模型的一种漏洞。不需要与服务器交互,只发生在客户端处理数据的阶段。请求一个经过专门设计的URL,其中包含XSS代码,服务器响应不会包含攻击者的脚本,当用户的浏览器处理这个响应时,DOM对象会处理XSS代码,导致存在XSS漏洞。
进阶
常用
<script>alert(hello)</script>
<img src=x onerror=alert(hello)>
<svg onload=alert(hello)>
<a href=javascript:alert(hello)>
常用XSS绕过编码策略
JS编码:
三个八进制数字,不够前面补0,e 为 \145
两个十六进制数字,不够前补0,e \x65
四个十六进制数字,e \u0065
对于一些控制字符,使用特殊dC类型的转义风格 \r
HTML实体编码:
实体命名:以&开头,以;结尾,“<”编码为&|t;
字符编码:十进制、十六进制ASCII码或Unicode字符编码,样式为“&#数值”,例如”<”可编码为<
和<
URL编码:
考虑HTML渲染顺序,针对多种编码组合时要选择合适的编码方式测试
修复
过滤输入:” ‘ ‘“、” “ “、“ < ” 、“ > ”、” on* “等非法字符
编码转换:对输出到页面的数据进行编码转换,HTML编码、JavaScript编码等
CSRF
跨站请求伪造漏洞,XSRF或CSRF
通过伪装成受信任的用户请求受信任的网站,不流行,难防范
原理:利用目标用户的身份,一目标用户的名义执行某些非法操作,威胁目标用户的财产安全
非法操作:以目标用户名义发送邮件、消息,盗取目标用户的账号,甚至购买商品、虚拟货币转账
攻击重点
目标用户已经登录了网站,能够执行网站的功能
目标用户访问了攻击者构造的URL
利用
CSRF漏洞常被用来制作蠕虫攻击、刷SEO流量
蠕虫攻击
burp 右键->Engagement tools->Generate CRSF PoC
修复
- 验证请求的Referer值开头是否为本网站,判断链接是否来自本网站,若不是服务器拒绝请求,也存在被绕过的可能
- 请求中放入攻击者无法伪造的信息,例如一个随机的token,通过验证token判断
SSRF
服务器端请求伪造,由攻击者伪造请求,由服务端发起请求的安全漏洞,一般SSRF攻击的目标是外网无法访问的内部系统。
原理
SSRF形成的原因大多数是由于服务端提供了从其他服务器应用获取数据的功能而且没有对目标地址做过滤与限制
攻击方式
- 对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息
Banner信息中可以的到软件开发商、软件名称、版本、服务类型等信息
- 攻击运行在内网或本地的应用程序
- 对内网Web应用进行指纹识别,识别内部的资产信息
- 攻击内外网的Web应用,主要使用HTTP GET请求就可以实现的攻击(struts2、SQLi)
- 利用file协议读取本地文件
漏洞利用
http://192.168.10.133/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1:3306
http://192.168.10.133/pikachu/vul/ssrf/ssrf_fgc.php?file=file:///C://wamp//123.txt
修复
限制请求端口只能为Web端口,只允许访问HTTP和HTTPS的请求
限制不能访问内网IP
屏蔽返回详细信息
文件上传
文件上传漏洞可以被利用,上传可执行脚本程序,可以获取网站的权限或进一步危害服务器
原理
服务端代码未对客户端上传的文件进行严格的验证和过滤
危害
上传Webshell
利用
JS检测绕过
- 使用浏览器插件,删除检测文件后缀的Js代码,然后上传文件
- 先把文件后缀改成允许的,绕过JS的检查,再抓包,包后缀改回、上传
文件后缀绕过
服务端代码禁止了某些后缀的文件,但有些Apache允许其他文件后缀,例如:httpd.conf中配置中有AddType application/x-htpd-php.php.phtml
如此就可以上传一个后缀为phtml的WebShell
Apache的解析顺序:从右到左,若最左侧扩展名不可识别,则继续往左直到可以解析
文件截断绕过
截断类型:PHP %00截断
原理:00代表结束符,00之后的字符删除
条件:PHP版本小于5.3.4,服务端将GET参数jieduan
的内容作为上传文件名的第一部分,然后将按时间生成的图片文件名作为上传文件名的第二部分
**过程:**修改参数jieduan
为1.php%00.jpg,文件被保存到服务器时%00把.jpg和按时间生成的图片文件名全部截断,只剩下1.php
分析:多数情况在文件后加上HEX形式的%00用来测试截断,绕过截断后,如果还有文件名判断,则不成功
竞争条件
有些网站上传文件的逻辑是:先允许上传任意文件,然后检查上传的文件是否包含WebShell脚本,包含则删除;此时上传成功和删除之间有一段时间用来检查和删除,这段时间可以利用这段时间完成竞争条件的上传漏洞攻击
修复
- 通过白名单的方式判断文件后缀是否合法
- 对上传的文件进行重命名,例如rand(10,99).date(“YmdHis”).”jpg”
暴力破解
暴力破解的产生是由于服务器没做限制,导致攻击者可以通过暴力的手段破解所需要的信息,如用户名、密码、验证码等;暴力破解需要一个庞大的字典
修复
- 用户登录次数限制
- IP登陆次数限制(多用户同一个IP存在问题)
命令执行
应用程序有时需要调用一些系统执行命令的函数,如PHP中,stystem、exec、shell_exec、passthru、popen、proc_popen等函数可以执行系统命令,如果能控制这些函数就能将恶意命令拼接到正常命令中,从而造成命令执行攻击
攻击
Windows常用管道符:
- “|”:直接执行后面语句
- “||”:前面为假直接执行后面语句,前面只能为假
- “&”:前面为假直接执行后面语句,前面可真可假
- “&&”:如果前面为假直接出错且不执行后面语句,前面只能为真
Linux常用管道符
- ”;“:执行完前面再执行后面
- ”|“:显示后面语句的执行结果
- ”||“:当前面出错执行后面
- ”&“:前面为假直接执行后面语句,前面可真可假
- ”&&“:如果前面为假直接出错且不执行后面语句,前面只能为真
修复
- 尽量不使用命令执行函数
- 客户端提交的变量做好过滤和检测
- 使用动态函数之前确保函数是指定的函数之一
- 对于PHP语言来说,不能完全控制的危险函数最好不要使用
逻辑漏洞
逻辑漏洞指攻击者利用业务的设计缺陷,获取敏感信息或破坏业务完整性。一般出现在密码修改、越权访问、密码找回、交易支付金额等功能处。其中越权访问又有水平越权和垂直越权两种
原理
水平越权
相同级别(权限)用户或同一角色不同用户之间,可以越权访问、修改或删除其他用户信息的非法操作;可能造成大量数据泄露,严重的甚至会造成用户信息被恶意篡改。
垂直越权
不同级别之间的用户或不同角色之间用户的越权,例如普通用户可以执行管理员才能执行的功能。
逻辑缺陷表现为设计者或开发者在思考过程中做出的特殊假设存在明显或隐含的错误
精明的攻击者会特别注意目标应用程序采用的逻辑方式,并设法了解设计者与开发者可能做出的假设,考虑如何攻破这些假设,黑客在挖掘漏洞时有两个重点:业务流程和HTTP/HTTPS请求篡改
**支付订单:**在支付订单时可以篡改价格为任意金额;或者可以篡改运费或其他费用为负数,导致总金额降低
**越权访问:**通过越权漏洞访问他人信息或操纵他人账号
**重置密码:**重置密码时,存在多种逻辑漏洞,比如利用session覆盖重置密码、短信验证码直接在返回的数据包中等
**竞争条见:**竞争条件常见于度多种攻击场景,前面的文件上传;再有就是购物场景,余额10,A6元B5元,分别购买余额不足,利用竞争条件,使用多线程同时购买AB可能的结果:AB其中之一失败;AB都成功只花了6元;都成功余额变-1
修复
越权访问漏洞产生的主要原因时没有多用户身份进行判断和控制,可以通过session来控制,例如将username或uid写入到session中,当用户查看个人信息时,从session中取出username,而不是从GET或POST取username,此时是nameuser才是未被篡改的
session与cookie:cookie数据保存在客户端,session数据保存在服务端。
XXE漏洞
XML外部实体注入漏洞,简称XXE漏洞,、
XML 和 HTML :XML 被设计用来传输和存储数据,其焦点是数据的内容。XML 旨在传输信息。
HTML 被设计用来显示数据,其焦点是数据的外观。
常见XML语法:
在 XML 中,有 5 个预定义的实体引用:
< | < | less than |
---|---|---|
> | > | greater than |
& | & | ampersand |
' | ‘ | apostrophe |
" | “ | quotation mark |
常见XML语法结构
<?xml version="1.0"?>
<!--XML声明-->
<!DOCTYPE note[<!ELEMENT note (to,from,heading,body)><!ELEMENT note (#PCDATA)>
<!--文档类型定义(DOM)-->
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>]><note><to>Tove</to>
<from>Jani</from>
<!--文档元素-->
<heading>Reminder</heading>
<body>Don't forget me this weekend</body></note>
其中,文档定义(DTD)可以内部引用外部DTD
- 内部声明DTD格式:<DOCTYPE 根元素 [元素声明]>
- 引用外部DTD格式:<DOCTYPE SYSTEM “文件名”>
DTD中进行实体声明时,将使用ENTITY关键字来声明。实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体可以在内部或外部进行声明
- 内部声明实体格式:<ENTITY 实体名称 “实体的值”>
- 引用外部实体格式:<ENTITY 实体名称 SYSTEM “URL”>
攻击
可以查看文件内容
<?xml version="1.0"?>
<!DOCTYPE a[
<!ENTITY b SYSTEM "file:///c:/windows/win.ini">
]>
<a>&b;</a>
查看php源代码,得到base64加密内容,解密后得到源码
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=c:/phpstudy_pro/WWW/pikachu/vul/rce/rce.php" >
]>
<foo>&xxe;</foo>
扫描开放端口,可以使用BurpSuite的Intruder功能爆破端口
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >
]>
<foo>&xxe;</foo>
服务器上的代码主要是simplexml_load_string()函数中使用了LIBXML_NOENT参数,导致外部实体可以被解析,才造成了xxe漏洞
//考虑到目前很多版本里面libxml的版本都>=2.9.0了,所以这里添加了LIBXML_NOENT参数开启了外部实体解析if(isset($_POST['submit']) and $_POST['xml'] != null){
$xml =$_POST['xml'];//
$xml = $test;
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
if($data){
$html.="<pre>{$data}</pre>";
}else{
$html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>";
}}
若没有LIBXML_NOENT参数,则需要哦内部实体才能被解析
<?xml version="1.0"?> <!DOCTYPE foo [
<!ENTITY xxe "XXElalal" >
]>
<foo>&xxe;</foo>
修复
- 禁止使用外部实体,例如lib_disable_entity_loader(true)
- 过滤用户提交的XML数据,防止出现非法内容
WAF
WAF:Web Applaction Firewall,Web 应用防火墙
通过一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品
分类
软件型:安装在web服务器上,可以直接检测服务器上是否存在WebShell、是否有文件创建
硬件型:以硬件形式部署在链路中,支持多种部署方式,当串联到链路中可以拦截恶意流量,在旁路监听模式下时只记录攻击不进行拦截
云WAF:一般以反向代理的形式工作,通过配置NS记录或CNAME记录,使网站的请求报文优先经过WAF主机,经过WAF主机过滤后,将确认无害的请求报文再发送给实际网站服务器,可以说使带防护功能的CDN。
**CDN:**CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
网站内置的WAF:也可以说是网站系统中内置的过滤,直接镶嵌在代码中,相对来说自由度高,一般分几种情况
- 输入参数强制转换
- 输入参数合法性检测
- 关键函数执行(SQL执行、页面显示、命令执行等)前,对代码流程的输入进行检测
- 输入的数据进行替换过滤后再继续执行代码流程(转义/替换掉特殊字符等)
网站系统内置WAF与与业务更加契合,在对安全业务都比较了解的情况下可以减少误报与漏报
判断
**sqlmap:**使用sqlmap中自带的WAF识别模块,若无特征识别类型为Generic
sqlmap.py -u "http://xxx.com"——identify-waf——bath
但是这条命令以及废弃了
**手工判断:**在URL后加测试语句/?aaa=1 union select 1,2,3%23
,且放在一个不存在的参数名中,看是否触发WAF防护(页面无法访问、响应码不同、返回与正常请求页面不同等)
绕过
主要SQL注入漏洞的绕过方法
**大小写混写:**uNion sElEct 1,2,3,4,5
URL编码,其中还有URL二次编码的情况,
替换关键字:WAF采用删除或者替换select/union这类关键词,如果只匹配一次就很容易绕过:unuionion selselectect 1,2,3 ,4
**使用注释:**注释在截断SQL语句中用的比较多,在绕过WAF时主要 使用注释代替空格(/*任意内容*/
),使用于检测过程中没有识别注释或者替换掉注释的WAF,例如:union/*2333*/select/*aaaa*/1,2,3,4
**多参数请求拆分:**对于多个参数拼接到同一条SQL语句的情况,可以将注入语句分割插入例如:请求URL时,GET参数a= [input1] &b= [input2] 将GET参数a,b拼接到SQL语句中a=union/*&b=*/select 1,2,3,4
**HTTP参数污染:**当同一参数出现多次,不同的中间件解析为不同的结果
**生僻函数:**使用生僻函数代替常见的函数,例如:报错注入中使用polygon()函数替换常用的updatexml()函数
SELECT polygon((select*from(select*from(select@@version)f)x));
**寻找网站源站IP:**对于有云WAF的网站,找到网站的IP,通过IP访问就可以绕过WAF
注入参数到cookies中:
某些程序员在代码中使用$_REQUEST获取参数值会依次从GET/POST/cookie中获取参数,如果WAF只检测了SET/POST而没有就检测cookie,可将注入语句放入cookie中进行绕过