人人网 好友真相 漏洞通告 | Renren App XSS Vulnerability Report

更新(2011.7.31.0:30):今天终于和人人网工作人员取得联系了。比较惊奇的是“好友真相”是一个人人网内部研发的应用,不是第三方应用。现在此漏洞已经被修复,请不要尝试了。不过这个方法还是可以给任何用户发送信息的,只是做了类似第二条建议的筛查而已。期待着这个应用的完善。KnH工作室的工作在此告一段落。同时,我们要感谢可爱的Chrome娘,助力这次漏洞的快速发现。KnH还会继续关注Internet上的不安全问题,创建安全网络(不是和谐)!

以下存档:今天在许多人的“被动推荐”下,我启动了人人的称作 好友真相的 插件。出于好奇,看了看页面源代码,着实让我胆战心惊。现在发布这个文章来通告一下人人的用户,如果您还在使用这个插件就要小心了哦。

Update: I came into contact with the Renren Development Staff today (31/7 0:30). I’m happy to announce that this leak has been successfully patched. Please do not try it as it will not work anymore. Although, the current patch only implements the fix described in #2, using the AJAX problem, users can still send to non-friends, and arbitarily modify the name section.

Attention all Renren.com users, the KnH Internet Security Club has just found an XSS vulnerability in one popular Renren.com app – 好友真相. If you are reading this blog post and are also using this app, please be careful about potential exploits. A successful exploit will allow a third party to insert ANY CODE (Javascript, Embed Objects…) into the App’s Page. Please be warned.

下面是错误报告的全部信息 / Below is a full disclosure of the bug :
首先我们分析这个人人应用的运作模式:好友真相是一个Iframe人人应用,使用了OAuth 模块和Renren API实现好友列表的调取和信息读取 。应用采取了2 个单元,_toUserName,_toUserId,保存了你要发送真相到的用户 ID 和他的姓名。由于这个APP利用人人API问题,无法直接通过ID 获取 人人用户名,则也就为XSS提供了可乘之机。

免责条款:以下内容请不要尝试,如果忍不住,必须获得对方的同意。利用网络软件的安全隐患进行用户隐私的侵犯是违反中华人民共合国法律的行为!KnH.C不对你利用这方法惹上麻烦负责。

进行一次有效的XSS攻击,分为如下步骤:
1. 寻找发送对象的 人人ID ,这个APP根据ID确定显示给谁,所以需要被攻击人ID。
2. 写一个比较好的代码,注入到姓名里面。

经过分析代码,我们看到,在回答好友真相问题的界面有很多AJAX调用,当然,我们最关心的是这个:

function answer(score){
		var url = 'http://truth.renren.com/truth/screen/index,ajaxAnswerScreen.php';
		jQuery.ajax({
   			type: "post",
   			url: url,
   			data: "qId="+document.getElementById('_qId').value+"&score="+score+"&toUserId="+document.getElementById('_toUserId').value+"&toUserName="+document.getElementById('_toUserName').value+"&toUserHeadurl="+document.getElementById('_toUserHeadurl').value+"&sessionId=381453503_146540_2.62c365e7b0a73016668f1f1799133a32.3600.1311948000-381453503",
   			success: function(msg){
   				if(msg == 5){
   					 msgDiag("答题奖励 ","您回答了5道题目,奖励一颗钻石,每天可以通过答题最多获得20枚钻石");
   				}
				getQuestion();
   			}
 		});
	}

看看里面拖红的部分,这是我们的关键。在每次选择完毕“真相Yes/No/Maybe”之后,那个flash(对,选择器是个flash片)会调用 answer(score) 函数发布你选择的是否度(score:int[0-100])。同时,你回答的用户也会被传送到好友真相的服务器(注意这不是人人的服务器),并被记录入数据库。

关键问题出在了这里,因为 _toUserName,_toUserId 是HTML页面的2个元素,用Chrome控制台打开输出后发现 _toUserId=2XXXXXX的数字,根据意思领悟发现是人人id(比如url:http://www.renren.com/home?id=38abc3def)这部分。_toUserName 居然惊人的是一个用户名字符串(如:“张三”,“约翰阿布尼”你懂的)。

所以在控制台执行了 :

document.getElementById('_toUserId').value="1234567";
document.getElementById('_toUserName').value="<script language='text/javascript'>top.location.href='注入地址';</script>";
answer(100);

奇妙的事情就发生了= =
“成功添加真相”诶!?

为了测试,我们设计 _toUserId=自己人人ID,执行如下代码,发现确实自己收到了自己给自己发的真相(这….)。点击查看真相,发现页面确实被跳转了(这……….)。

危害:由于这个插件会发送人人“提醒”,用户很可能被诱导点击页面(点击直接进入了含有供给代码的页面)。而且用户无论如何无法删除一条真相(很悲剧),所以每次访问这应用,代码就必被执行。而且,虽然应用里面只允许你选择你的好友,但是实际操作中,你可以输入任何人人用户ID,而且都会成功(这是关键问题…)。

当然KnH演示的JS脚本是一个用户很能察觉到的(为了测试)。恶意利用此漏洞者,可能允许执行代码获取用户人人session,进而实现Session Hijack(会话劫持),同时,如果保留 _toUserName 原有部分而仅仅追加JS代码,用户根本无法察觉攻击。精明的代码还可能在用户查看后,自动调用发送函数,将恶意代码发送到那个用户关联的好友,实现全站迅速传播。

所以在此奉劝AJAX作者:
1、不要认为AJAX来的数据是可信的,因为AJAX是执行在用户端的代码,普通用户没事不会看源代码,但是总有人看吧?
2、做好数据筛查:一行简单的preg_replace(‘~[<>]~’,”,$text); 就可以避免直接的XSS攻击。还有 SQL注入,往往也在AJAX下被遗忘。
3、把名字(函数、变量)起得难懂些:我相信如果 answer() 叫 a() ,_toUserName叫 param839,_toUserId 叫 param774,那么没有人会费尽功夫研究这代码 ,更不会有这样的发现了。
4、代码做好隐藏、压缩:把这个包裹到JS里面、然后把空行空白都去掉,变成一行js,也会大大降低被分析概率。

同时,对这个应用的作者:你写软件要道德,你这个纪录完用户数据就不删除了= =,看看你主页的恶评。这年代要保护隐私,比被XSS攻击更可怕的是有漏洞的本身就是个记录器
(这句更新:作者解释此插件并非成熟期,有很多不妥,我们静观其动向再对插件的ethics评判)

后续:这个BUG已经报告给人人客服和原作者,不过应用作者并不太像很关注这问题的样子。文章仅供作为教训,至于到时候这漏洞能不能使,本作者希望不能,但是这也不在我的掌控范围内。

24 Comments

    1. 用Chrome右键那个Iframe里面页面,“审查元素”,然后就可以找到代码了。
      我上次测试大概在8月初,可以更改姓名,“ XXX 给你发送了一条真相”的XXX是可变的,也可以随意选人发送(好友以外的)。不过这些问题都报告人人技术部了,至于什么时候修或者说是不是就懒得修了…我倒不清楚。

      如果愿意你可以用Chrome查看源码、查看元素,执行JS的话 打开“ Console”就可以了,输出数值什么的…

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注