三、Pikachu靶场XSS漏洞实战

1、反射型XSS

在上篇文章中我们对反射型的XSS做了简单的实践,为了加深我们对反射型XSS的理解,我们通过Pikachu靶场的源码来进一步认识反射型XSS:

我们按照提示输入kobe,发现它的输出和源码中显示的内容一致,这里它定义的message会原封不动地输出到P标签里面,没有做任何的过滤和限制,就是一个单纯的文本环境上下文,因此我们上篇文章中构造的payload就可以让后台执行代码,实现弹窗:

<script>alert("xss")</script>

2、存储型XSS

存储型XSS所实现的效果和反射型最大的区别就是,存储型xss可以实现将payload储存在留言板中,我们每次访问该界面都会自动跳出弹窗,这样看来存储型的xss带来的危害就要比反射型大的多,接下来我们来通过题目具体认识一下。

大家可以看到这里我做了很多的尝试,留言列表的前两个大家可能比较眼熟,是这样,有留言列表这样表头的地方就有概率会出现SQL注入漏洞,这两句payload正是我们之前文章中提到的报错注入的payload:

1' or updatexml(1,concat(0x7e,version()),0)#

我们发现这里的SQL注入并没有产生报错,说明该网页的源码对我们的SQL语句在拼接时进行了转义,我们继续回到对XSS的尝试,还是像反射型测试时一样,尝试单双引号和左右尖括号这种payload中的敏感字符,看看是否会被转义,提交后发现可以直接构造payload,那么思路就和上次一样了,我们直接去看它的界面源码:

我们找到了自己输入的位置也在一个<p>标签中,并且会把这样的输入去存储在一个表(留言列表)中,我们通过分析上下文的简单关系,直接写入payload即可:

<script>alert("xss")</script>

大家可以切换一个界面后再次进入该界面,你会发现这个xss的弹窗由会重新弹出,不仅如此,每个进入该网页的用户使用该界面的时候都会弹出一个xss弹窗,这就是因为我们输入的payload已经被永远存储在该表单中了,最后让我们一起在pikachu后台的源码中看看这里的配置存在什么安全隐患:

通过这些后台的源码我们就可以完全理解我们输入的payload是经过了怎样的处理,我们输入的内容(message)都直接存储到了mysql数据库的data字段,每次访问都会将数据库里的内容直接在<p>标签内执行,大家可以在代码块里面详细看看:

<div id="xsss_main">
        <p class="xsss_title">我是一个留言板:</p>
        <form method="post">
        <textarea class="xsss_in" name="message"></textarea><br />
        <input class="xsss_submit" type="submit" name="submit" value="submit" />
        </form>
        <div id="show_message">
        <br />
        <br />
        <p class="line">留言列表:</p>
        <?php echo $html;
        $query="select * from message";
        $result=execute($link, $query);
        while($data=mysqli_fetch_assoc($result)){
        echo "<p class='con'>{$data['content']}</p><a href='xss_stored.php?id={$data['id']}'>删除</a>";
}

echo $html;
?>

3、DOM型XSS

DOM型的XSS和反射与存储型存在一些区别,在学习这种XSS之前,我们需要先认识一下什么是DOM?

可以把DOM理解成一个访问HTML的标准编程接口,通过JavaScript,就可以重构整个文档,我们可以添加、移除、改变或重新排版以上的项目。

对DOM有一个初步的概念后,我们来到具体的环境里看看DOM型的XSS如何利用:

我们还是拿到这样一个输入框,在这里我们随便输入一些字符,发现它给了我们一个what do you see?的回显,我们来看看前端的源码是如何编写的:

源码会将我们输入的text写入dom的这样一个foution中,我们可以看到实际上的最终输出其实是在一个<a>标签之中的what do you see?

foution{
    var str = document.getElementByid("text").value;
    document.getElementByid("text") innerHTML "<a href = '"str+"'>what do you see?</a>;
}

不知道大家是否有所发现,整个输入输出的过程不涉及和后台数据库的交互,整个流程全发生在前端的DOM之中,这样一来我们只需要抓出实际输出的部分,对它原本的<a>标签进行一下修改:

我们单独把整个<a>标签拎出来:

<a href = '"str+"'>what do you see?</a>

这里我们试图给它提前闭合<a>标签,这里的思路就是构造闭合,可能会让人联想到SQL注入漏洞中构造 or 1=1 恒等式以及单引号的闭合问题,两种思路有很多相似之处:

<a href = '' onclick="alert('xss')">'><what do you see?</a>;

还可以在闭合以后加入新的标签:

<a href = ''><img src="#" onmouseover="alert('xss')">'>what do you see?</a>;

构造好以后我们来看看这次要具体输入的payload是哪些部分吧:

' onclick="alert('xss')">
'><img src="#" onmouseover="alert('xss')">

我们把这两种构造思路分别进行尝试吧:

插入后我们再次点击what do you see?就可以跳出这个弹窗了,这就是DOM型XSS的一个简单情景下的实现过程。但是很多人可能会对此产生疑问,这样一来即便我们可以跳出一个弹窗又有什么意义能,我们所输入的内容不会对其它使用该界面的用户产生什么实质性的危害,既然作为安全漏洞,DOM型XSS是否像很多人说的那样鸡肋呢?

当然不是,我们可以看下面这样的一个同样为DOM型XSS漏洞的题目:

我们随机输入一个字符串,跳出一句话“有些费尽心机想要忘记的事请,后来就真的忘掉了”,我们来一起看看它的界面源码是怎么编写的:

这里很明显看到一个DOM的操作,发现参数是从浏览器的URL里面获取的,最后和上面一样是以dom的形式输出,虽然这样的编写一样不会经过后台的交互,但是会和浏览器的URL产生联系,我们依旧使用刚刚的payload来进行测试:

我们再次点击“就让往事随风,都随风吧”这句话,成功跳出一个XSS的弹窗,这时看向我们的URL:

我们输入的payload赋给text的操作保留在了URL里面,这时我们只需要将这个URL发送给我们要攻击的目标,只要它点击这样的URL,他就被我们XSS攻击了。这就是DOM型具体的一个攻击形式,并非人们口中的那样鸡肋,攻击使用的URL其实并不好辨认出它的攻击性,很多人不留意就会进行点击,这样造成的危害也是巨大的。

本篇文章到这里也要结束了,我们已经分享了三大类型的XSS漏洞,下篇文章中将分享这三种类型的具体应用,强化我们对XSS漏洞的使用理解。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐