web

成功就是要梭哈Writeup | 公开赛

Posted by Pwnhub on 2017-12-12

对于本期公开赛,胖哥只有一幅图表达心声:

接下来开始我们的梭哈之旅吧!(同时感谢本期公开赛的出题胖友:@wupco ,港真,这是我见过最认真负责的出题胖友啦~全程盯 log ,233333

PS:本期只收到两份 WP ,想要多赠送一点邀请码的胖哥表示很遗憾。依然盼望邀请码的小伙伴们欢迎关注胖哥微博——胖哈勃,即时获取新动态喔!


通过查看所有题目代码,可以看到有注入点,但经过;的过滤、sqlchop和preg_match的检测,如果绕不过就直接die掉。如果能顺利bypass这两个,就可以传给mysql -e去处理,当然后面用了escapeshellarg 所以想直接拼接命令的怕是不行了。

代码如下:

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
<?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);
?>

0X01 命令行下的mysql

Alt text

命令行进入mysql,输入\h会发现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
27
28
List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
? (\?) 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.
For server side help, type 'help contents'

其中\c 可以清空前面的内容,也就是我前面无论输入了什么,都可以被清空忽略掉,既从\c后面开始真正的sql语句。

\d可以指定sql语句的分割符号,也就是可以用其他字符替代掉;的功能

\n可以关闭页设置,注意它是可以出现在sql语句的几乎任何位置的,比如
Alt text

\p 可以显示之前输入的部分sql语句的内容

\u 可以指定选择一个库

\! 可以执行linux bash命令

到这里,你可以选择注入,也可以选择先利用\!getshell

####0X01 getshell

先执行一下ls -l ,发现没什么可读的

Alt text

读一下根目录呢?

发现都不可写,同时有个getflag是 -rwx—— 只有root用户有权限读写执行。

Alt text

执行ps aux发现没返回结果,猜测是被禁用掉了。

执行netstat -ant 发现 localhost 8888端口绑了一个服务。

Alt text

让我们弹个shell先

上面拦截了.符号,还是很容易绕过的,你可以采用任意方法,比如可以用base64编码命令用管道去解码执行,也可以用ip的其他进制……
注意如果使用xargs 搭配一些常用命令会被sqlchop拦截,不过也可以绕过,比如curl你可以写成/usr/bin/cur*
Alt text
Alt text

我们nc一下localhost的8888端口,发现需要一个key,翻了很多文件都没找到,可以猜测是在数据库里了,猜不到也没关系,在/home/ubuntu/下有个flag文件
Alt text
Alt text

####0X02 注入 or 拿密码

所以只要在库中找到key就行了,这里有很多办法,可以利用mysql的bash特性绕过sqlchop拿到,也可以找到数据库连接密码。

先说说直接拿密码吧,虽然禁用掉ps命令,但还是可以查看/proc/里对应pid的cmdline看到密码的。

于是可以直接执行 cat /proc/*/cmdline 拿到数据库连接串
Alt text
直接利用mysql -e就能拿到key了。

那么如何通过web服务直接拿到密码呢?
可以利用\c清空前面的select 1 from dual where 1= ,然后后面拼接show databases 直接看库
Alt text

然后如何看表呢?可以利用\u 选中flag库,也可以利用\d改变语句分割符,即可执行多条sql语句。
Alt text
Alt text

最后from被拦截通过\n截断from就ok
Alt text

Alt text