DVWA之XSS

OK呀咱们也是打上靶场了

先来整个XSS(Reflected)

初级形态(low)的靶场

1
<script>alert('xxx')</script>

一串小代码直接弹窗,说明执行成功,毫无过滤,轻松拿下

中级形态(medium)的靶场

1.一串小代码

1
<script>alert('xxx')</script>

结果没运行,响应了一串Hello alert(‘xxx’),一看,爷的script呢?十成让这小可爱给我过滤了, 分析一下源码找一下证据,发现medium比low多了一行

1
$name = str_replace( '<script>', '', $_GET[ 'name' ] );

喝,长大了!知道要过滤了。但是你过滤script关我Script什么事?拿下。

2.当然了也可以双写绕过

1
<sc<script>ript>alert('xxx')</script>

高级形态(high)的靶场

还是经典的先试一试

1
2
<script>alert('xxx')</script>
<Script>alert('xxx')</Script>

两个语句的响应都是Hello >说明这次的过滤更全面,话不多说,我们直接红温开摆。。。。。。不好意思,当成打王者了。现在我们进一步,看一下关键源码,看看他是如何过滤的

1
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

很明显这是把script标签过滤掉了

那我们继续尝试一些其他XSS攻击方式

1
<img src="" onerror="alert('XSS')">

发现执行成功。拿下这关。

超进化形态(impossible)的靶场

一般impossible情况下,单独利用漏洞就比较困难了,这里我们学习一下过滤方式,读一下源码

我们大致读一下就会发现,主要用来过滤的字段大概就是

1
$name = htmlspecialchars( $_GET[ 'name' ] );

我们来了解一下htmlspecialchars这个函数

htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。

预定义的字符是:

(这里因为html实体在Typora里实在难打出来,所以这里用截图的方式)

<>被转化成html实体后,其语言标签就不会再被识别,那些输入的代码自然不会被执行

XSS(Reflected)结束

接下来上场的是XSS(Stored)

低级形态(low)

其实总体的payload大致也没太变,我们来学习一下存储型xss的过滤手段

读一下源码发现里面的过滤函数有:

trim()

函数移除字符串两侧的空白字符或其他预定义字符。

语法:trim(string,charlist) ;string(必需,规定要检查的字符串) ; charlist(可选,规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符:

“\0” - NULL

“\t” - 制表符

“\n” - 换行

“\x0B” - 垂直制表符

“\r” - 回车

“ “ - 空格

)

stripslashes()

删除字符串中的反斜杠

语法:stripslashes(string);string(要操作的字符串)

但是仔细查看源码,没有对script脚本进行过滤

所以我们的payload还可以用

1
<script>alert('kevin')<script>

但是我们插入的时候会发现第一个框有长度限制,但是没关系直接f12

将maxlength的值改大就行,再插入payload就没问题啦。

中级形态(medium)

来到中级形态,还是老样子尝试一下之前的经典payload

1
<script>alert(document.cookie)</script>

很可惜message直接展示出来了,说明script标签被过滤掉了,没有执行

去看源码,我们发现他已经对massage板块使用了htmlspecialchars() 函数,massage框已经不可能注入了

但是name框只是比较简单的str_replace过滤,那么我们完全可以在name框位置进行插入

还是大写绕过

1
<SCRIPT>alert(document.cookie)</SCRIPT>

或者双写绕过

1
<scr<script>ipt>alert(document.cookie)</script>

但是我们发现name框有长度限制,那么我们可以直接f12改长度限制,或者bp抓包改txtName字段就行

高级形态(high)

查看源码

massage还是htmlspecialchars函数;而name框则使用了preg_replace函数调用正则表达式的方法,对script做逐字匹配,并使用/i来不区分大小写。

补充一下preg_replace() 函数:

preg_replace()

函数执行一个正则表达式的搜索和替换。

语法:(有些用法我也没太看明白,我写一下自己理解的用法)

preg_replace($pattern, $replacement, $string);$pattern: 就是你想如何搜索,可以是字符串或一个字符串数组。

$replacement: 是用于替换的字符串或字符串数组。

$subject: 要搜索替换的目标字符串或字符串数组。

那么payload便不能再用script标签了

payload就可以是

1
<img src="" onerror="alert('XSS')">

插入方式刚刚在中级形态教过了

超进化形态(impossible)

这个形态就是把两个框都用了htmlspecialchars函数

彻底杜绝了xss攻击

最后咱们把dom型来整一整

初级形态(low)

初级形态没啥意思,跟之前的都一样,就是插入点不太一样

变成了English这个位置

中级形态(medium)

查看源码

先补充一下stripos() 函数

stripos()

函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。

语法:stripos(string,find,start);string:必需,规定被搜索的字符串。

find:必需,规定要查找的字符。

start:可选,规定开始搜索的位置。

这段代码就是先看提交的GET请求里是否存在名为"default"的参数,并且该参数的值不为空。如果存在,则将其值存储在变量$default中,并进一步检查其是否包含<script>标签。如果包含,则重定向到?default=English

看下前端源码

找到value值是从这里来的

image-20240526212551480

那么我们可以尝试闭合它来执行

知识补充

’option‘ ’/select‘都是双标签,也就是说会识别两个标签之间的语句,那么我们就人为把它闭合起来,在执行过程中,一旦存在一对标签,那么就会执行这里面的语句,无法构成成对标签的不会执行里面的语句,而’<img‘是单标签,也就是说他要执行的语句涵盖在它里面。>闭合前面<option

所以构造闭合,我们直接

1
></option></select><img src=x:alert(alt) onerror=eval(src) alt=xss>

插入点不变。

高级形态(high)

由于是高级形态,就直接看源码了

image-20240526214606110

很明显的看到,这是一个白名单。

image-20240526215437971

我们又发现是以form表单提交的

那就可以利用

由于 form表单提交的数据 想经过JS 过滤 所以注释部分的javascript 代码 不会被传到服务器端(也就符合了白名单的要求)

payload:

1
#<script>alert(/xss/)</script> 

超进化形态(impossible)

image-20240526220616950

读一下代码,学一下人家是怎么防御的

最后备注一下

我之前看到有些人在对script标签过滤的绕过中,会在script标签里加入\

这其实是利用某些浏览器或解析器的容错机制。这些机制有时会忽略某些字符或错误,从而导致原本应该被过滤的标签仍然被识别并执行。

虽然没啥用,但是给我这样的小白添加了一些知识面。

欸嘿!结束了!吃饭喽!