既然提示有源代码泄露,我们就先扫描一遍。
精选CTF专用字典:
https://github.com/gh0stkey/Web-Fuzzing-Box/blob/main/Dir/Ctf.txt
推荐使用7kbscan进行扫描,
https://github.com/7kbstorm/7kbscan-WebPathBrute
线程调成1,然后加载字典,找到svn 那应该就是SVN源代码泄露。
index.php
<?php include 'flag.php'; session_start(); defined('black_hat') or header("Location: route.php?act=index"); if(isset($_SESSION['hat'])){ if($_SESSION['hat']=='green'){ output("<img src='green-hat-1.jpg'>",10); echo "<br><br><br><a href='logout.php'>妥妥的绿帽子,再给你一次机会吧!</a>"; }else{ output("<img src='black-fedora.jpg'>",1); echo $flag; echo "<br><br><br><a href='logout.php'>哎呦不错哦,再来一次。</a>"; } }else{ output("<img src='white-hat.jpg'>",10); echo "<br><br><br><a href='login.php'>哥想知道自己的真正实力!</a>"; } function output($content,$count){ for($i=0;$i<$count;$i++){ echo $content; } }
login.php
<?php defined('black_hat') or header('Location: route.php?act=login'); session_start(); include_once "common.php"; $connect=mysql_connect("127.0.0.1","root","root") or die("there is no ctf!"); mysql_select_db("hats") or die("there is no hats!"); if (isset($_POST["name"])){ $name = str_replace("'", "", trim(waf($_POST["name"]))); if (strlen($name) > 11){ echo("<script>alert('name too long')</script>"); }else{ $sql = "select count(*) from t_info where username = '$name' or nickname = '$name'"; echo $sql; $result = mysql_query($sql); $row = mysql_fetch_array($result); if ($row[0]){ $_SESSION['hat'] = 'black'; echo 'good job'; }else{ $_SESSION['hat'] = 'green'; } header("Location: index.php"); } } ?>
common.php
<?php error_reporting(2); session_start(); $connect = mysql_connect("127.0.0.1", "root", "root") or die("error 1"); mysql_select_db("hats") or die("error 2"); function d_addslashes($array){ foreach($array as $key=>$value){ if(!is_array($value)){ !get_magic_quotes_gpc() && $value=addslashes($value); waf($value); $array[$key]=$value; } } return $array; } function waf($value){ $Filt = "\bUNION.+SELECT\b|SELECT.+?FROM"; if (preg_match("/".$Filt."/is",$value)==1){ die("found a hacker"); } $value = str_replace(" ","",$value); return $value; } function is_login(){ $sid = $_COOKIE["sid"]; $data = explode("|",$sid); if($data[0] && $data[1] && $data[1] == encode($data[0])) { return $data[0]; } return FALSE; } function encode($str){ $key = sha1("Fuck_you_man"); return md5($key.$str); } function set_login($name){ $data = encode($name); setcookie("sid","$name|$data"); } ?>
route.php
<?php header('Content-Type: text/html; charset=utf-8'); define("black_hat", 'icq'); include("common.php"); $_POST=d_addslashes($_POST); $_GET=d_addslashes($_GET); $file = $_GET['act'].".php"; if (!is_file($file)){ die("not hats"); } include_once($file); ?>
当$_SESSION['hat'] = 'black';时,在index.php下面就能获取到flag
在login.php中发现SQL语句:
select count(*) from t_info where username = '$name' or nickname = '$name'
我们只要利用or 1=1就能让结果不为空
继续看common.php的代码发现传入的name经过了waf函数,过滤了常见的union、select、from 同时过滤了空格
route.php是把post和get的数据addslashes了的,对'
过滤,但会保留\
。
用/**/
代替空格 然后通过or 1=1
以及#
注释掉后面的语句让整个语句恒真即可
最后构造Payload:or/**/1=1#'