Emlog某重要插件前台SQL注入+Getshell

EM相册是emlog最早的插件之一(插件页面:http://www.emlog.net/plugin/6 。id为6,可想而知),作者是现在身为emlog社区超版的KLLER,下载量也是很大的。 下载以后解压,看到kl_album_ajax_do.php: [php] query("INSERT INTO ".DB_PREFIX."kl_album(truename, filename, description, album, addtime, w, h) VALUES('{$_FILES['Filedata']['name']}', '{$upfname}', '".date('Y-m-d', time())."', {$album}, ".time().", {$photo_size['w']}, {$photo_size['h']})"); if($result){ $new_id = $DB->insert_id(); $the_option_value = Option::get('kl_album_'.$album); if($the_option_value !== null){ $the_option_value = trim($new_id.','.$the_option_value, ','); Option::updateOption('kl_album_'.$album, $the_option_value); $CACHE->updateCache('options'); } } } exit; } if(ROLE != 'admin') exit('access deined!'); if(isset($_GET['action']) && $_GET['action']!=''){... [/php] 可见,验证身份(倒数第二行)的代码在上传的代码后面,所以任意用户均可上传文件。那么我们来看看上传部分。里面似乎定义了一个$att_type = array('jpg', 'jpeg', 'png', 'gif');,并将$att_type这个变量和$_FILES一起传入了kl_album_upload_file函数。我们进去看看: [php] function kl_album_upload_file($filename, $errorNum, $tmpfile, $filesize, $filetype, $type, $isIcon = 0){ $kl_album_config = unserialize(Option::get('kl_album_config')); $extension = strtolower(substr(strrchr($filename, "."),1)); $uppath = KL_UPLOADFILE_PATH . date("Ym") . "/"; $fname = md5($filename) . date("YmdHis") . rand() .'.'. $extension; $attachpath = $uppath . $fname; if(!is_dir(KL_UPLOADFILE_PATH)){ umask(0); $ret = @mkdir(KL_UPLOADFILE_PATH, 0777); if($ret === false) return '创建文件上传目录失败'; } if(!is_dir($uppath)){ umask(0); $ret = @mkdir($uppath, 0777); if($ret === false) return "上传失败。文件上传目录(content/plugins/kl_album/upload)不可写"; } doAction('kl_album_upload', $tmpfile); //缩略 $imtype = array('jpg','png','jpeg','gif'); $thum = $uppath."thum-". $fname; $attach = in_array($extension, $imtype) && function_exists("ImageCreate") && kl_album_resize_image($tmpfile,$filetype,$thum,$isIcon,KL_IMG_ATT_MAX_W,KL_IMG_ATT_MAX_H) ? $thum : $attachpath; $kl_album_compression_length = isset($kl_album_config['compression_length']) ? intval($kl_album_config['compression_length']) : 1024; $kl_album_compression_width = isset($kl_album_config['compression_width']) ? intval($kl_album_config['compression_width']) : 768; if($kl_album_compression_length == 0 || $kl_album_compression_width == 0){ if(@is_uploaded_file($tmpfile)){ if(@!move_uploaded_file($tmpfile ,$attachpath)){ @unlink($tmpfile); return "上传失败。文件上传目录(content/plugins/kl_album/upload)不可写"; }else{ echo 'kl_album_successed'; } chmod($attachpath, 0777); } }else{ if(in_array($extension, $imtype) && function_exists("ImageCreate") && kl_album_resize_image($tmpfile,$filetype,$attachpath,$isIcon,$kl_album_compression_length,$kl_album_compression_width)){ echo 'kl_album_successed'; }else{ if(@is_uploaded_file($tmpfile)){ if(@!move_uploaded_file($tmpfile ,$attachpath)){ @unlink($tmpfile); return "上传失败。文件上传目录(content/plugins/kl_album/upload)不可写"; }else{ echo 'kl_album_successed'; } chmod($attachpath, 0777); } } } $attach = substr($attach, 6, strlen($attach)); return $attach; } [/php] 我们可以看看,实际上我们传入的$type这个变量在这个函数里根本没有用到! 函数中定义了一个$imtype = array('jpg','png','jpeg','gif');,也不是用来验证后缀的,而是判断是否需要生成缩略图的。所以重点就是下面几行: [php] $extension = strtolower(substr(strrchr($filename, "."),1)); $uppath = KL_UPLOADFILE_PATH . date("Ym") . "/"; $fname = md5($filename) . date("YmdHis") . rand() .'.'. $extension; $attachpath = $uppath . $fname; ... if(@!move_uploaded_file($tmpfile ,$attachpath)){ [/php] 这里,我们可以发现上传的文件名是md5($filename) . date("YmdHis") . rand() .'.'. $extension;,原名的md5值+时间+rand随机数+后缀。md5值和时间基本比较好确定的,但是rand()随机数一般都有65535个可能性。 而且我们看到后面的代码,并没有把文件名输出的地方,只是echo 'kl_album_successed';。 难道我们需要暴力跑shell名字? 我们返回kl_album_ajax_do.php,可以发现上传的if语句中有如下代码: [php] $result = $DB->query("INSERT INTO ".DB_PREFIX."kl_album(truename, filename, description, album, addtime, w, h) VALUES('{$_FILES['Filedata']['name']}', '{$upfname}', '".date('Y-m-d', time())."', {$album}, ".time().", {$photo_size['w']}, {$photo_size['h']})"); [/php] 将$_FILES['Filedata']['name']直接插入数据库。这里另造成了一个SQL注入漏洞,当然既然有之前的getshell,这里的注入就有点当陪衬了。不过emlog在遇到SQL语句出错的情况下是会报错的。 所以所以,这里我们正好用到这个特性,通过报错可以将$upfname这个字段爆出来,这也就是我们上传成功的shell名字。 如何报错?上传文件名里加个单引号即可。 所以,我来一份利用代码: [php]

target url >

shell file >

[/php] 1.png1.jpg 出错了,可以发现文件名已经爆出来了:../content/plugins/kl_album/upload/201411/38493d4468377f721357e9c64f93637d2014111211381611097.php 2 访问可见shell: 3 Author:phithon

发表评论