XSS原理及程式碼分析

前言

XSS又叫跨站腳本攻擊,是一種對網站應用程式的安全漏洞攻擊技術。它允許惡意用戶將程式碼注入網頁,其他用戶在瀏覽網頁時就會受到影響。XSS分為三種:反射型,存儲型,和DOM型。下面我會構造有缺陷的程式碼,從程式碼分析這三種類型。
如果想要了解XSS基礎的可以看我的這篇文章:XSS(跨站腳本攻擊)簡單講解
如果想要了解SQL注入原理的可以看我的這兩篇文章:SQL注入原理及程式碼分析(一)
SQL注入原理及程式碼分析(二)
參考文獻:《Web安全攻防》

反射型XSS

反射型XSS又叫非持久型XSS,這種攻擊方式往往具有一次性。
先看程式碼

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>xss利用輸出的環境構造程式碼</title>
</head>
<body>
<center>
    <h6>把輸入的字元串輸出</h6>
    <form action="#" method="get">
        <h6>請輸入</h6>
        <input type="text" name="xss" value="請輸入"><br />
        <input type="submit" value="確定">
    </form>
    <hr>
    <?php
        if (isset($_GET['xss'])) {
              echo '<input type="text" value="'.$_GET['xss'].'">';
        }else{
            echo '<input type="text" value="輸出">';
        }
    ?>
</center>
</body>
</html>

在程式碼中,通過GET獲取參數xss的值,然後通過echo輸出一個input標籤,並將xss的值放入input標籤的value中。
接下來我們看一下頁面,例如我們輸入123,會在下面的輸出框中輸出123。

那麼下面,我們當我們輸入"><script>alert(1)</script>時,輸出到頁面的HTML程式碼變為<input type="text" value=""><script>alert(1)</script>">我們發現,輸入的雙引號閉合了value屬性的雙引號,輸入的>閉合了input的標籤<,導致我們後面輸入的惡意程式碼成為另一個HTML標籤。

當瀏覽器渲染時執行了,JS函數alert()導致瀏覽器彈窗。

存儲型XSS

先看程式碼,參考dvwa的核心程式碼。

<?php

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

    // Sanitize message input
    $message = stripslashes( $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)) ? "" : ""));

    // Sanitize name input
    $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>' );
}
?> 

在上面程式碼中,獲取POST參數mtxMessage和txtName,然後將將參數插入到資料庫的表中,並顯示到頁面上。
頁面的功能是獲取用戶名字和內容並插入到資料庫中,如果我們輸入惡意程式碼,那麼也會插入到資料庫中,只有用戶訪問這個頁面,那麼惡意程式碼就會執行。

打開資料庫發現插入了我們構造的惡意程式碼。

DOM型XSS

先看程式碼

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />;
    <title>測試</title>
    <script type="text/javascript">
            function tihuan() {
                    document.getElementById("id1").innerHTML =document.getElementById("dom_input").value;
            }
    </script>
</head>
<body>
<center>
    <h6 id="id1">這裡顯示輸入的內容</h6>
    <form action="#" method="post">
           <input type="text" id="dom_input" value="輸入"><br />
           <input type="button" value="替換" onclick="tihuan()">
    </form>
    <hr>

</center>
</body>
</html>

DOM型XSS程式只有HTML程式碼,並不存在服務端程式碼,所以此程式並沒有與服務端進行交互。程式存在JS函數tihuan(),該函數得作用是通過DOM操作將元素id1得內容修改為元素dom_input的內容。
這個頁面得功能是輸入框中輸入什麼,上面得文字就會被替換成什麼。

如果我們輸入惡意程式碼,比如,單擊替換按鈕,頁面彈出消息框,由於隱式輸出,所以查看源程式碼時是看不到XSS程式碼的。

XSS修復建議

  1. 過濾輸入的數據包括但不限於單引號,雙引號,「<,>」等。
  2. 對輸出到頁面的數據進行相應的編碼轉換,包括HTML實體編碼,JavaScript編碼等。
Tags: