PHP代码审计之WEB安全系列基础文章(七)XSS篇
【如需转载,请详细表明来源,请勿设置原创】
嗨,大家好,我是闪石星曜CyberSecurity创始人Power7089。
欢迎大家扫描下方二维码关注 “闪石星曜CyberSecurity” 公众号,这里专注分享渗透测试,Java代码审计,PHP代码审计等内容,都是非常干的干货哦。
今天为大家带来PHP代码审计基础系列文章第七篇之XSS篇。
这是【炼石计划@PHP代码审计】知识星球第二阶段的原创基础系列文章,拿出部分课程分享给零基础的朋友学习。本系列原创基础文章涵盖了PHP代码审计中常见的十余种WEB漏洞,是匹夫老师精心的创作,欢迎关注我的公众号跟着一起学习。
【炼石计划@PHP代码审计】是一个系统化从入门到提升学习PHP代码审计的成长型知识星球。这里不仅注重夯实基础,更加专注实战进阶。强烈推荐加入我们,一起来实战提升PHP代码审计。
PHP代码审计之XSS(跨站脚本攻击)
pikachu靶场安装
在本节的部分内容会用到pikachu靶场来进行演示教学,pikachu源码会与文章一起下发,大家使用phpstudy将pikachu放入www进行搭建即可,具体搭建方法如下:
将源码放置在phpstudy中WWW目录下,修改inc/config.inc.php
文件,将phpstudy中设置的数据库用户名、密码以及端口填入,这里注意如果数据库端口不是默认的3306,那么需要在DBHOST中跟端口号。
这里选择pikachu
根目录即可,PHP版本建议使用PHP7以下的版本。
然后点击上方的初始化进行安装
如果出现如下内容就表示安装成功了。
1.XSS原理
XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本 攻击缩写为XSS,他的中文名称为:跨站脚本攻击。而XSS的重点不在于跨站,而在于XSS中执行的JavaScript脚本情况。
Web程序代码中把用户提交的参数未做过滤就直接输出到页面,参数中的特殊字符被恶意进行闭合造成原有的html页面被嵌入恶意的脚本内容,黑客可以利用该漏洞执行恶意JavaScript代码,当用户浏览该页之时,嵌入其中Web里面的JavaScript代码会 被执行,从而达到恶意攻击用户的目的。
2.XSS分类
XSS常被分为三种类型:
- 反射型XSS:直接将HTTP请求中的用户可控数据输出到HTML页面中的跨站脚本注入,由于用户可控数据没有被存储,因此只能在单次请求中生效。
- 存储型XSS:又叫特久型XSS,直接将HTTP请求中的用户可控数据存储至数据库中,再从数据库中读取出来输出到HTML页面上,由于数据经过存储,可以持续被读取,攻击影响面和危害都较高。
- DOM-XSS:特殊的反射型XSS,将用户可控数据通过JavaScript和DOM技术输出到HTML中,利用方式通常与反射型XSS类似。
2.1 反射型XSS
反射型XSS对于访问者来说是一次性的,当攻击者将构造好的恶意URL发送给访问者,访问者点击URL将我们的请求传递给服务器,服务器将不加处理的脚本“反射”回访问者的浏览器而使访问者的浏览器执行相应的脚本,最简单的代码如下。
反射型XSS执行方式:浏览器——>后端——>浏览器
示例代码:
1 |
|
我们通过参数xss
传入我们自定义的XSS脚本,脚本被前端页面解析并执行。
在页面右击查看源码处我们可以发现我们输入的JavaScript脚本。
2.2 存储型XSS
存储型XSS与反射型XSS的区别在于,存储型XSS是被存储在数据库中的,攻击者只需将JavaScript脚本输入,后端将攻击者输入的JavaScript脚本保存到数据库中,访问者在每次访问存在XSS页面时存储在数据库中的JavaScript脚本就会被执行。
存储型XSS执行方式:浏览器——>后端——>数据库——>后端——>浏览器
在pikachu
存储型XSS靶场中存在如下代码:
xss_stored.php
这里代码24-26行,通过POST接收参数后,将数据插入到数据库中。
这里代码80-83行,通过select
查询数据库中刚才插入的数据并通过echo
输出content
字段内容,在这个过程中将我们插入的数据保存到数据库中并且进行任何过滤所以造成存储型XSS。
这里我们输入JavaScript代码,成功执行并弹窗。
在数据库中也可以发现我们的JavaScript代码被存储到数据库中。
2.3 DOM型XSS
DOM型XSS与反射型XSS差不多,只不过DOM型XSS中会调动一些JavaScript中的函数来获取客户端提交的内容,定义了一个节点名字和值,然后再返给客户端。
DOM型XSS执行方式:URL-->浏览器
在pikachu
DOM型XSS靶场中存在如下代码:
xss_dom.php
在这里接收一个GET传入的值
在代码56-58行,表单中调用domxss()
函数,在代码49-50行,获取text
内容赋值给变量str
并拼接到a href标签中通过innerHTML将内容输入到页面。
通过闭合’>将我们想要执行的JavaScript代码分离出来
3.XSS审计函数
在XSS审计中我们其实多关注一些输出打印函数即可,它们的作用就是将输入的内容显示在前端页面,只要这些函数中内容可控且输出前没有进行完善的过滤就会造成XSS漏洞。
1 |
|
4.XSS审计注意点
4.1 htmlspecialchars函数
在htmlspecialchars()
函数中,默认情况下不会对'
进行转义,如果是代码中像下面这种情况,传入的text内容,在下面的input表单中输出且是被单引号包裹,我们就可以闭合单引号,在标签内构造XSS来绕过htmlspecialchars()
函数。
1 |
|
我们可以在标签内闭合单引号,然后通过onclick在标签内构造一个点击事件来触发XSS。
4.2 编解码中存在的问题
很多时候开发在写代码时存在一些逻辑缺陷,导致过滤函数无法发挥实际的效果,如下代码中首先通过text传入参数,然后紧接着对传入的参数进行htmlspecialchars()
实体化编码,这里似乎没有问题。但浏览器的运行机制会默认对传入的参数进行一次url解码,由于代码中最后一段又进行了一次url解码并使用echo
输出。那么我们就可以对传入的内容进行两次url编码来绕过htmlspecialchars()
函数的过滤,从而造成xss。
1 |
|
我们对中特殊字符进行两次URL编码%253Cscript%253Ealert('xss')%253C/script%253E
,由于浏览器会首先对我们传入的数据进行一次URL解码,变成%3Cscript%3Ealert('xss')%3C/script%3E
,在传入htmlspecialchars()
函数时就会绕过该函数的过滤,在最后echo
时又进行一次URL解码,最终还原我们的JavaScript代码<script>alert('xss')</script>
。
5.XSS代码审计总结
1 |
|