web安全--JSONP注入实践

JSONP注入实践

JSONP注入实践

Stbird

Stbird

专注于互联网信息安全的科技媒体http://www.mottoin.com

1 人赞同了该文章

原文链接:http://www.mottoin.com/95682.html

---------------------------------------------------------------------------------------------------------------------------

JSONP注入是一个鲜为人知的但是非常广泛和危险的漏洞。它在近几年才出现,由于JSON,web API和跨域通信的急需。

什么是JSONP

假设每个人都知道JSON是什么,让我们谈谈一下JSONP。 JSONP来自带有填充的JSON,被创建来绕过常见的限制,例如同源策略。

举个例子。 我们的网上银行应用程序,http://verysecurebank.ro,实现了一个返回当前用户的交易的API调用。
访问http://verysecurebank.ro/getAccountTransactions的HTTP请求向我们提供了当前用户的交易内容,JSON格式:

 

如果我们的报告应用程序,想访问http://reports.verysecurebank.ro获得交易详细信息,由于同源原则生效(不同的主机),将无法通过AJAX调用该页面。

为了解决这个问题,JSONP发挥了作用。 由于跨域脚本包含(主要用于外部加载JavaScript库,如jQuery,AngularJS等)是允许但不推荐的,一个聪明的技巧显然解决了整个问题:在响应前加上回调。

注意:即使它可能是显而易见的,值得提及的是,当包括脚本跨域时,它将在包含应用程序的上下文中运行,而不是在源的上下文中运行。

添加一个回调到API响应,包裹JSON格式的数据,允许我们加载脚本标签之间的API响应,并通过定义我们自己的回调函数来处理它的内容。

怎么使用JSONP

这是你最容易遇到的情况:

  1. 回调函数在响应中硬编码
  • 基本函数调用
  • 对象方法调用

2.回调函数是动态的

  • 完全可控的URL(GET变量)
  • 部分可控的URL(GET变量),但附加一个数字
  • 可控的URL(GET变量),但最初不显示在请求中

基本函数调用

一个非常常见的示例,其中myCallback回调在响应中硬编码,包裹在JSON格式的数据上:

我们可以通过首先定义myCallback函数,然后在脚本标签中引用API调用来轻松使用它:

注意:确保在包含响应之前定义函数,否则将调用未定义的函数,并且不会获取任何数据。

当登录的受害者访问我们的恶意页面时,我们抓取他的数据。 为了简洁起见,我们在当前页面中显示整齐格式化了的数据。

对象方法调用

这几乎与第一个示例相同,你可能会在ASP或http://ASP.NET Web应用程序中遇到它。 在我们的示例中,System.TransactionData.Fetch作为回调围绕JSON格式的数据被添加:

我们只是为已经是System对象一部分的TransactionData对象创建Fetch方法。

结果是相同的,所以没有截图。

完全可控的URL(GET变量)

这是你会遇到的最常见的情况。 回调函数在URL中指定,我们可以完全控制它。 回调URL参数允许我们更改回调的名称,因此我们将设置它来测试,并在响应中看它的改变:

我们基本上可以使用相同的代码,但是不要忘记在包含带有脚本标签的响应时添加回调参数。

部分可控的URL(GET变量),但附加一个数字

在这种情况下,回调函数名称附加了一些东西,通常是一个数字。 在大多数情况下,我们得到的东西像jQuery和一个附加到它的短号,像12345,回调成为jQuery12345。

逻辑上,代码保持不变,我们只需要将12345添加到我们的回调函数名称,而不是包含脚本时。

但如果数字不是硬编码怎么办? 如果是动态的、每个会话都不同怎么办? 如果它是一个相对较短的数字,我们可以用过编程预定义每个可能性的函数。 让我们假设附加的数字高达99999。 我们可以以编程方式创建所有这些函数,所以附加的数字,我们已经有一个回调函数。 这里是示例代码,我使用一个更简单的回调来说明结果:

这里发生了什么:我们有硬编码的回调名称jQuery,我们为函数的数量设置了一个限制。 在第一个循环中,我们在callbackNames数组中生成回调函数名。 然后我们循环遍历数组,并将每个回调名称转换为全局函数。 请注意,为了缩短代码,我只提醒第一笔交易中发送的金额。 让我们看看它是如何工作的:

 

在我的机器上,花了大约5秒钟显示警报,回调名称为jQuery12345。 这意味着Chrome在5秒内创建了超过10.000个功能,所以我大胆地说,这是一个很可行的方法。

可控的URL(GET变量),但最初不显示在请求中

最后一个场景涉及一个显然没有回调的API调用,因此没有可见的JSONP。 这可能发生在开发人员,为其他软件或代码留下隐藏的向后兼容性只是没有在重构时删除。 因此,当看到没有回调的API调用时,特别是如果JSON格式的数据已经在括号之间,手动添加回调到请求。

如果我们有以下API调用http://verysecurebank.ro/getAccountTransactions,我们可能会尝试猜测回调变量:

这些只是最常见的回调名称,请随意猜测更多。 如果我们的回调被添加到响应,bingo,让我们道德地抓取一些数据。

基本数据抓取

因为我们直到现在才显示数据,让我们看看如何把它发送给我们。 这是JSONP数据抓取的一个小示例,可以将其用作概念验证。

 

我们发送应用响应(比如用户的交易内容)在data参数中的get请求给我们的数据抓取器。

注意:确保对数据使用了JSON.stringify(),因为它是一个对象,我们不希望在我们的文件中只有[object Object]。

注意:如果响应很大,请确保切换到POST,因为HTTP GET的大小限制,可能无法接收完整的数据。

这里是我们的grabData.php代码,我们将接收到的数据追加到data.txt文件中:

常见问题

在寻找JSONP漏洞的Web应用程序时,我们可能会遇到一些问题。 这里我们尝试解决他们。

Content-Type和X-Content-Type-Options

如果在API请求的响应标头中,X-Content-Type-Options设置为nosniff,则必须将Content-Type设置为JavaScript(text/javascript,application/javascript,text/ecmascript等)来在所有浏览器上生效。 这是因为通过在响应中包含回调,响应不再是JSON,而是JavaScript。

如果您想知道浏览器解释为JavaScript的内容类型,请访问JavaScript MIME type

在此示例中,Content-Type设置为application / json,X-Content-Type-Options设置为nosniff。

 

最新版本的Google Chrome,Microsoft Edge和Internet Explorer 11成功阻止了脚本执行。 但是,Firefox 50.1.0(目前是最新版本)没有。

注意:如果X-Content-Type-Options:nosniff头未设置,它将适用于所有上述浏览器。

注意:旧版本的浏览器没有考虑严格的MIME类型检查,因为最近实现了X-Content-Type-Options。 根据Mozilla,这是由于浏览器的兼容性:

响应码

有时我们可能会得到一些其他响应代码,而不是200,特别是当我们搞乱了响应。 我在这些浏览器上进行了几个测试:

  • Microsoft Edge 38.14393.0.0
  • Internet Explorer 11.0.38
  • Google Chrome 55.0.2883.87
  • Mozilla Firefox 50.1.0

发现了这些不一致:

因此,即使我们没有获得200 HTTP代码,该漏洞仍然可以在其他浏览器中使用。

绕过referer检查

1.使用data URI scheme

如果有HTTP Referer检查,我们可以尝试不发送它来绕过验证。 我们怎么能做到这一点?通过data URI。 我们可以利用data URI scheme,以便在没有HTTP Referer的情况下发出请求。 因为我们处理的代码,包括引号,双引号和其他语法破坏字符,我们将对base64编码我们的payload(回调定义和脚本包含)。

语法:

data:text/plain;base64,our_base64_encoded_code

 

以下是允许我们使用data URI scheme的三个主要HTML标签:

  • iframe(在src属性中) – 它在Internet Explorer中不起作用
  • embed(在src属性中) – 它在Internet Explorer和Microsoft Edge中不起作用
  • object(在data属性) – 它在Internet Explorer和Microsoft Edge中不起作用

我们可以看到,API请求中没有发送HTTP Referer。

2.从https到http的请求

如果我们的目标网站可以通过HTTP访问,我们还可以通过在HTTPS页面上托管我们的代码来避免发送HTTP Referer。 如果我们从HTTPS页面发出HTTP请求,则浏览器不发送Referer头以防止信息泄露。

我们所有要做的只是在启用HTTPS的网站上托管我们的恶意代码。

注意:由于混合内容安全机制,这不适用于具有默认设置的现代Web浏览器。 受害者已手动接受浏览器的安全警告。

 

但是,它在旧版本的浏览器中使用,并且不发送HTTP Referer头,我们可以看到:

我们如何解决这个问题

最后,让我们看看我们如何防止这种情况的发生。 最直接和最现代的方法是CORS(跨源资源共享)。

  1. 完全删除JSONP功能
  2. 将Access-Control-Allow-Origin标头添加到API响应中
  3. 使用跨域AJAX请求

因此,http://reports.verysecurebank.ro将以下跨域AJAX请求嵌入到http://verysecurebank.ro/getAccountTransactions

API响应包括Access-Control-Allow-Origin:http://reports.verysecurebank.ro

 

我们得到http://verysecurebank.ro/getAccountTransactions的内容:

结论

虽然JSONP使用量在减少,但仍然有大量的网站依然在使用它。 作为最后一个提示,当处理JSONP时,也不要忘记检查反射型文件下载和反射型xss。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Element-plus和Axios都是基于原生的XMLHttpRequest对象实现的,而JSONP是一种不基于XMLHttpRequest对象的跨域请求机制,因此使用JSONP需要使用其他库或者自己实现跨域请求的代码。 JSONP(JSON with Padding)是一种简单的跨域数据传输方式,它通过动态创建`<script>`标签来实现跨域请求。JSONP的原理是利用`<script>`标签的跨域特性,在请求中使用一个回调函数名作为参数,服务器端将数据包装在该回调函数中返回,客户端通过该回调函数来获取数据。 使用JSONP时需要注意以下几点: 1. 服务器端需要支持JSONP请求,并在响应中返回符合JSONP规范的数据。 2. 客户端需要定义一个全局的回调函数,并将该函数名作为请求参数发送给服务器端,服务器端将数据包装在该函数中返回。 3. 由于JSONP是通过`<script>`标签实现的,因此服务器端返回的数据必须是可执行的JavaScript代码,而不是普通的JSON格式数据。 以下是一个使用纯JavaScript实现的JSONP请求的示例代码: ```js function jsonp(url, callback) { const script = document.createElement('script') const callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random()) window[callbackName] = function(data) { delete window[callbackName] document.body.removeChild(script) callback(data) } const query = url.indexOf('?') === -1 ? '?' : '&' script.src = url + query + 'callback=' + callbackName document.body.appendChild(script) } ``` 以上代码定义了一个`jsonp`函数,用于发送JSONP请求。该函数接受两个参数,第一个参数是请求的URL地址,第二个参数是回调函数,用于处理服务器端返回的数据。 在Element-plus项目中使用JSONP时,可以将以上代码封装成一个单独的模块,然后在需要发送JSONP请求的地方引入该模块,例如: ```js import jsonp from './jsonp' jsonp('https://example.com/api/data', function(data) { // 处理服务器端返回的数据 }) ``` 需要注意的是,JSONP请求具有一定的安全风险,因为服务器端返回的数据是可执行的JavaScript代码,可以在客户端执行任意的JavaScript代码。因此在使用JSONP时需要仔细考虑安全问题。如果需要更安全的跨域请求方式,可以使用CORS或者其他技术来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值