推荐:Oracle  web环境注射技术

作者:剑心

前言    

本人不是个专业数据库管理员也不是个专门研究oracle安全研究员文中语句很多都写得非常不专业对数据库理解也不够甚至很多语句可能在区别版本上并不适合些技术也是牛人们很早提到过本文只是从个web安全角度来看如何入侵台被防火墙防护Oracle数据库些入侵技术做了web入侵上整理总结和延伸尽量将原理讲得明白本文也并没有对sql注射中存在些共性进行讨论 如利用substr和经典注射这些而是站在oracle数据库角度尽量展现些Sql注射入侵思路以及如何利用数据库些特性在web上做最大入侵些牛人工具也即将发布出来希望还有人喜欢手工优美注射

、Oracle 简单介绍

Oracle作为款比较早期出现RDBMS数据库市场占有率比较大经常用在些大型数据库上它本身除了很好地支持各种SQL语句外还提供了各种丰富存储过程甚至支持java和创建library等特性如此强大功能为Hacking提供了很好便利

Oracle自身有很多默认帐户并且有很多存储过程这些存储过程是由系统建立很多默认都是对public开放在过去几年里公布了很多oracle漏洞包括溢出和SQL注射在内许多漏洞在这里面SQL注射漏洞显得格外严重在Oracle里在不加其他关键字AUTHID CURRENT_USER情况下创建存储过程在运行时是以创建者身份运行而public对这些存储过程都有权限所以旦自带存储过程存在注射很容易让普通用户提升到Oracle系统权限Oracle本身内置了很多帐户其中些帐户都有默认密码并且具有CONNECT权限这样如果oralce端口没有受到防火墙保护又可以被人远程连接就可以被人利用默认帐户远程登陆进系统然后利用系统里存储过程SQL注射漏洞系统就会沦陷当然登陆进oracle还需要sid不过这也并不困难oracletnslener默认没有设置密码完全可以用tnscmd.pl用services命令查出系统sid(到比较新版本这个漏洞已经被修复了)这也是非常经典入侵oracle方式

2、Oracle Web Hacking 技术背景

    oracle丰富系统表oracle几乎所有信息都存储系统表里当前数据库运行状态当前用户信息当前数据库信息用户所能访问数据库和表信息......系统表就是整个数据库核心部分通过恰当地查询需要系统表几乎可以获得所有信息如sys.v_$option就包含了当前数据库些信息如是否支持java等all_tables里就包含了所有表信息all_tab_colmuns包含所有列信息等等为我们获得信息提供了非常大便利后面将有有关如何利用系统表获取敏感信息描述

在oracle各种漏洞里需要特别说下存储过程注射其实也并没有什么神秘存储过程和样是接受用户输入然后送到数据库服务器解析执行如果是采取组装成SQL形式执行就很容易将数据和命令混淆导致SQL注射但是根据注射发生点区别样地注射漏洞性质也区别Oracle使用是PL/SQL漏洞发生在select等DML语句不支持多语句执行所以如果想运行自己语句如GRANT DBA TO LOVEHSELL这些DDL语句就必须创建自己或存储过程如果没有这相关权限还可以利用cursor注射用dbms_sql包来饶过限制大多数注射正是上面这些有限制注射必须依靠自己创建些其他包或者cursor来实现提升权限但是还是有些非常少见但是注射环境非常宽松漏洞就是用户输入被放在begin和end的间匿名pl/sql块注射这种环境下注射可以直接注射进多语句几乎没有任何限制而可以看到正是这种闪光漏洞为我们web注射技术带来了怎样辉煌

好了上面谈到都是Oracle些攻击技术但是现在很多环境是对外开放web服务后台数据库被防火墙保护着无法得到数据库太多详细信息已经不能直接登陆进数据库进行操作这个时候就要考虑利用web下漏洞来攻击后台数据库了现在来看下如何进行Oracle web环境下注射吧!oracle可以在各种web环境下良好地工作各种web环境对我们注射影响也并不是很大在asp.netjsp中对进入参数基本没做任何过滤但是由于.netjsp语言是强类型语言在数字类型注射上即使sql语句没有做过滤但是可能在接受参数时候就出错了所以注射出现在串类型参数上比较多在php环境下所有'会被转义为\'在oracle环境里\'并不会成为转义(在oracle环境里正确转义应该为'')但是在我们自己注射语句里使用'会被转成\'而遭到破坏所以在注射时不能使用'除此的外web环境下就没什么限制了在数据库方面如果语句采取是参数方式执行也不能够被注射除非使用串连接方式(由于串连接方式比较简单些历史上原因很多员往往会偏向于这种方式)串连接方式话也会分为两种参数在selectupdateinsert这些DML语句的间和参数在pl/sql匿名块的间如果web没有捕获那么我们很容易根据判断出当前语句类型后面会提到在pl/sql匿名块的间比较少见但也不排除这样注射基本也是没有什么限制可以执行多语句做任何事跟本地登陆没有任何区别

3、Oracle Web Hacking 基本思路

下面说说如何确定目标注射参数确定就由大家自己来了主要是如何判断数据库属于oracle根据数据库特性很容易判断出来oracle支持--类型注释但是不支持;分隔执行多语句oracle有很多系统表譬如all_tables通过对这些表访问也可以判断出是否属于oracle另外在oracle里也可以用来判断譬如utl_http.request这些语言上小细节也可以用来区分系统譬如在oracle里||是连接符号但是在其他数据库里就不是了所以 and chr(123)||chr(123)=chr(123)||chr(123)这样如果可以顺利执行那么就基本应该是oracle了另外些脚本在出现数据库查询信息没有处理也会泄露真实后台数据库这个可以很明显地看出来

然后需要确定是注射点类型情况下我们进入参数不是数字类型就基本是类型(其他很多人所说搜索型注射其实还是应该归结于类型)对于数字类型基本不用考虑什么很容易添加--注释就可以让语句正确闭合了如果是类型就要考虑如何让整个语句正确通常是添加'以及--这些注射来构造自己注射环境些复杂情况下如同个参数在多个sql语句和逻辑里出现就要自己小心构造出符合环境注射语句了记住我们只需要个能便利插入自己sql命令完好环境:)

在确定目标数据库为Oracle并且可以注射时候就可以开始尝试构造语句了般首先要进行是判断当前权限在Oracle数据库里权限比较高是DBA权限拥有Oracle数据库所有权限另外如果当前用户权限授予不对也可以实现跨库查询效果可以通过对dba_tables这样dba表进行尝试访问来测试是否是dba注射中分为select类型注射insert类型注射以及update类型等update和insert类型注射可以根据上下文来更改数据库中数据如利用update注射将表中某个重要字段更改成我们想要即使这些数据库无关紧要也没关系我们可以利用select子语句来将我们需要数据查询出来然后在另外某个地方将这个数据读出来只要遵循数据库语法实现自己就可以了在这里主要说下select类型注射如果我们能控制select语句部分就可能实现这种类型注射如果查询结果可以返回到页面中时候还可以尝试使用union查询出结果直接将内容显示在页面当中这是最方便事实上后面可以看到无论是什么注射在oracleweb环境下都可以直接执行系统命令返回shell

Oracle中获得敏感数据首先就是oracle有系统表任何有权限获得数据都可以从这里获得关键系统表有all_tablesall_objects等都是有权限能访问包括别人赋予你权限所以如果你权限是dba这能看到系统中所有注射中个窍门技巧就是如果你需要从后台登陆但是不知道密码就可以在这里使用了譬如猜测列名含不含有password等思路方法后面例子中也有讲述

另外比较需要了解就是union查询在oracle union查询中和其他数据库类似要求列数还要求类型完全oracle类型有很多常见类型数字类型以及日期类型等等般我们能用来做union查询并且显示类型所以需要精确定位哪个字段符合我们要求(1 会在页面显示数据从进入到出来会有很多流程很多数据会在中间经过多次处理所以要想找到能显示出来数据很多时候并不是那么顺利这种显示包括很多地方包括返回http头页面正文甚至是cookie等    2 类型 我们出来数据大部分都是类型所以需要这个类型用来正确地匹配  3长度需要足够 尽管我们可以用来解决这个问题但是够长字段总是非常简便 )oracle并不会自己做数据类型转换但是oracle中提供了个NULL类型可以匹配所有数据类型所以我们在定位完字段数的后就可以在union各个字段填写null来匹配另外oracle不支持select 1这样查询语法要求select必须有关键字如果我们没有表可以用可以用系统中默认谁都有权限表dual有关定位字段数其实也比较简单和其他数据库样可以利用order by 1-- 这样操作如果字段个数存在就会正常通常页面逻辑会让这个参数 不只在个地方出现所以order by地方不所以不能进行union查询在这里可能会遇到目标语言不支持''情况所以可以使用chr这些来处理这些问题

即使不支持unionoracle些特性还是让我们轻易拿到想要信息就是用系统utl_http.request包这个包你可以看做是个普通用来取得远方web服务器请求信息所以我们完全可以自己监听端口然后通过这个用请求将需要数据发送过来这个时候我们还可以用来查看数据库可不可以上网以及出口IP是个非常重要正是有了这些系统里丰富包和以及存储过程使得只要有个注射点就可以在oracle里做任何事情包括权限允许和权限不允许记住是任何事

敏感数据只是我们想要部分通常直接杀入oracle可能更有吸引力这个时候查看系统信息就非常地有价值了对注射灵活运用也非常重要oracle在启动的后把系统要用些变量都放置到些特定视图当中可以利用这些视图获得想要东西通常非常重要信息有

1、当前用户权限    (select * from session_roles)
2、当前数据库版本    (select banner from sys.v_$version where rownum=1)
3、服务器出口IP    (用utl_http.request可以实现)
4、服务器监听IP    (select utl_inaddr.get_host_address from dual)
5、服务器操作系统    (select member from v$logfile where rownum=1)
6、服务器sid    (远程连接话需要select   instance_name   from   v$instance;)
7、当前连接用户    (select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual)
......

知道上面这些的后就可以大致清楚服务器是在外网还是内网支不支持远程连接如果支持远程连接就可以尝试用默认密码和刚得到sid登陆了在获得本地权限的后就可以尝试利用众多包里面存在注射提升权限了在http://www.milw0rm.com/搜索oracle关键字可以找到很多这样漏洞

如果是远程并且不允许连接我们还是可以利用包sql注射我上面说可以做任何事可以利用个注射点轻易获得shell上面说到在oracle里包注射分好几种这里需要就是pl/sql块注射这个注射允许直接执行多语句所以我们可以在web注射里利用这个直接以sys身份执行多条语句如添加用户创建自己存储过程等等几乎没有限制但是系统这种注射也是非常地少见在06年被人公布过也就是SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES具体漏洞可以不了解我也没有找到细节后面有我做些简单黑盒分析对于我们也只需要知道这是系统里存在个存储过程pl/sql注射可以导致执行多语句就可以了而且oracle补丁机制还不是很完善基本上不会有管理员去patching这些所以在我们看来就把这当作是系统提供执行多语句个Hacking接口好了如果你遇到个sql注射本身就是在pl/sql里话没那么更要恭喜你了 :)

通过上面几步基本让你可以获得你想要东西并且可以得到个可以执行多语句环境在多语句执行环境里就可以利用oracle本身强大功能如支持java创建外部存储过程支持utl_file包写文件等等很方便地利用java写个shell或者直接利用java包返回个系统shell

4、真实世界里注射

那么个真实世界注射应该是个什么样子呢?让我们试试如何从注射点来获得个shell:)

首先我们找到个可能存在注射页面list.jsp?username=loveshell我们添加个'结果出错了通过爆出知道这是个oracle后台数据库如含有ORA-xxxx这样都是oracle然后用语句:
    list.jsp?username=loveshell' and ''||'1'='1    正常
    list.jsp?username=loveshell' and ''||'2'='1    返回空
    list.jsp?username=loveshell'--

这样可以知道是个oracle类型注射点那么我们就可以用这种方式插入自己SQL语句了
    list.jsp?username=loveshell' and [我们sql语句] --

这个时候我们就可以根据自己目标考虑后续入侵思路了种是向web方向发展通过查询数据库信息来渗透web种就是直接入侵数据库当然最完美情况下是oracle和web是台机器先说说如何查询数据库里存储信息吧!要想取得信息就要将信息反馈回来种是利用union查询譬如这里我们入侵手法类似于下面:
    list.jsp?username=loveshell' order by 10 --     如果信息被反馈话应该会出现xx coloum不存在的类字段数小于10
    list.jsp?username=loveshell' order by 5 --    正常显示字段数大于5
   ......
    最后发现到order by 8时候order by 7 就正常介绍说明是7个字段注意这里时候页面逻辑很简单所以可以这样order by猜测但是如果这个参数进入了2个以上sql语句里面结果字段数不就难用这种思路方法了当然如果进入2个以上Sql语句估计union查询也无法使用了sql语句前后字段数会不无法满足条件后面我们将说到种万能获取数据思路方法这里先说比较直观union查询
    list.jsp?username=loveshell' union select NULL,NULL,NULL,NULL,NULL,NULL,NULL from dual--    用7个NULL来匹配对应字段不会出现字段类型不情况和mysql区别后面select语句必须加个存在这里是dual
    这里正常返回然后我们就可以继续了寻找用做信息反馈字段需要满足我上面在基本思路里几个条件
    list.jsp?username=loveshell' and 1=2 union select 1,NULL,NULL,NULL,NULL,NULL,NULL from dual--
       正常
    list.jsp?username=loveshell' and 1=2 union select 1,2,NULL,NULL,NULL,NULL,NULL from dual--
       第 2个字段不是数字类型
    list.jsp?username=loveshell' and 1=2 union select 1,'2',NULL,NULL,NULL,NULL,NULL from dual--
        第 2个字段不是类型



Tags: 

延伸阅读

最新评论

发表评论