-
Notifications
You must be signed in to change notification settings - Fork 19
/
README
331 lines (284 loc) · 15 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
simple fuzz
by: aaron conole <[email protected]>
synopsis
simple fuzz is exactly what it sounds like - a simple fuzzer. don't mistake
simple with a lack of fuzz capability. this fuzzer has two network modes of
operation, an output mode for developing command line fuzzing scripts, as well
as taking fuzzing strings from literals and building strings from sequences.
simple fuzz is built to fill a need - the need for a quickly configurable
black box testing utility that doesn't require intimate knowledge of the inner
workings of C or require specialized software rigs. the aim is to just provide
a simple interface, clear inputs/outputs, and reusability.
features
simple script language for creating test cases
support for repeating strings as well as fixed strings ('sequences' vs.
'literals')
variables within test cases (ex: strings to be replaced with different
strings)
tcp and udp payload transport (icmp support tbd)
binary substitution support (see basic.a11 for more information)
plugin support (NEW!) see plugin.txt for more information.
previous packet contents inclusion
intro - the problem
why'd i write this? i was going to use spike for black box testing at work,
but the problem with that is - how do i get the people in SQA to be able to
really hammer away at my stuff? they're not software engineers and in many
cases are barely competent programmers. giving them a bulky C program, based on
SPIKE that might require heavy modification seemed like i would be setting
myself up for maintenance nightmares, and insufficient code coverage.
but - SPIKE is very powerful, very flexible, and VERY well known. this is
true but has one caveat: all the power and flexibility and apple pie of SPIKE
comes at the cost of a steep learning curve. it requires time to learn, and
if/when a bug might surface, would require time delving into internals which I
don't want to be 'the guy' for at work.
intro 2 - the solution
write my own, more simple fuzzing software. I'm not gonna pretend I know a
whole lot about which other fuzzers exist. I saw a webpage that rattled them
off like everyone had written them. maybe they have, and I'm late to the party.
what I took away from most of the reading was this: all those fuzzers are very
specialized. seriously. there are fuzzers which contain their own IP stacks for
testing and mapping OS behavior. i certainly don't need that.
intro 3 - so what do i have
a pretty simple fuzzer. it is reminiscent of easy-fuzz from 2004 written by
priest of the priestmasters. his layout for building a fuzzy test was pretty
nice. a "script" file, with a preamble - setting some basic state and
variables, followed by the "meat and potatoes" tests. since i really liked this
approach, i sto^H^H^Hborrowed it for my own. naturally, since i wrote my code
from scratch i was able to do things i wanted without being tied to his design
decisions.
chapter 1 - using rotting fruit to make a fuzzy engine
so - how to use. the utility takes only a few commandline options, which i'll
list here for posterity:
output modes:
-O
this option sets the engine to run in output mode
-T
this option sets the engine to run in TCP mode
-U
this option sets the engine to run in UDP mode
logging:
-L filename
this option specifies a file to write instead of the standard output
-n
this option will start a new log file after each fuzz attempt
-X
this option specifies that the fuzz outputs to the log / screen should be
printed as a hexadecimal dump.
config file:
-f filename
this option specifies the fuzzing "script" - covered later.
network host:
-e
this option stops testing when the host fails to respond.
-S host
this option sets the remote host to which we will connect
-p port
this sets the port for the host to which we will connect.
-t timeout
this sets an amount of time (minimum of 100) in MILLIseconds to wait
for a response. your best bet would be to run a sniffer (crappy one
included) and watch the responses that way.
variables:
-D variable=value
sets a fuzzing test case variable to be replaced with value. every
occurance of the variable will be replaced.
note: if you set a variable 'foo' equal to 'bar' then %foo would be equal to
strlen('bar'). See basic.nuke.crlf for the canonical example.
misc:
-b number
starts fuzzing at test case 'number'
-q
sets "quiet" mode - output will only contain fuzzed payload (if -O is
specified) and the potential response.
-v
sets "verbose" mode - output will contain extra information
-l
transmit literals only.
-s
transmit sequences only.
-r
do not send a trailing newline (generally used for binary fuzzing)
help:
-V
shows the version information
-h
shows the help
chapter 2 - scraping together caterpillars
so, now that you know how to execute the fuzzer, we need to setup a script.
the first thing when writing the script is to understand all the 'reserved'
parts. so here are the keywords, and what they do. note: only FUZZ is case
sensitive.
___________________________________________________________________________
| keyword | meaning
+-----------------+--------------------------------------------------------
| # | when used at the start of a line, denotes a comment
+-----------------+--------------------------------------------------------
| // | when used at the start of a line, denotes a comment
+-----------------+--------------------------------------------------------
| ; | when used at the start of a line, denotes a comment
+-----------------+--------------------------------------------------------
| literal | used to assign a string that should be inserted to a
++++++++++++++++++| fuzzing test case "literally". ex: literal=abcd
+++++++++++++++++++--------------------------------------------------------
| sequence | used to assign a string that should be sequence filled
+++++++++++++++++++ into a fuzzing test case. ex: sequence=A
+++++++++++++++++++--------------------------------------------------------
| seqstep | used to set a step increment for fuzz sequences. ex:
+++++++++++++++++++ seqstep=1 with a maxseqlen=30 would create fuzz strings
+++++++++++++++++++ of size 1 - 30 for each sequence.
+-----------------+--------------------------------------------------------
| lineterm | replaces the end of line character with the text specified
+++++++++++++++++++ ex:
+++++++++++++++++++ # the following makes every test case terminate with \r\n
+++++++++++++++++++ !CRLF=0d 0a
+++++++++++++++++++ lineterm=CRLF
+++++++++++++++++++--------------------------------------------------------
| reppol | used to indicate which policy to use when substituting data
+++++++++++++++++++ from previous packets. Valid values are always and once.
+++++++++++++++++++ always indicates that the substitution string should be
+++++++++++++++++++ refreshed with packet data after every packet.
+++++++++++++++++++ once indicates that the substitution string should only be
+++++++++++++++++++ refreshed after the first time it is recovered.
+++++++++++++++++++--------------------------------------------------------
| reqwait | sets the time to wait between requests in milliseconds
+-----------------+--------------------------------------------------------
| maxseqlen | sets the maximum size that a sequence can fill
+-----------------+--------------------------------------------------------
| include | includes a secondary config file, which must be
+++++++++++++++++++ terminated with an endcfg line. use absolute paths.
+++++++++++++++++++--------------------------------------------------------
| endcfg | terminates the configuration block. all blocks following
+++++++++++++++++++ will be interpreted as parts of fuzzing requests. therefore
+++++++++++++++++++ no comments are allowed to go in the testing blocks. it is
+++++++++++++++++++ probably a good idea to fill up comments at the beginning
+++++++++++++++++++ which describe all of the tests that are to be executed.
+++++++++++++++++++--------------------------------------------------------
| -- | used to denote the "end" of a block of text representing
+++++++++++++++++++ a test.
+++++++++++++++++++--------------------------------------------------------
| c- | used to denote the "end" of a block of text representing
+++++++++++++++++++ a test. indicates that the system should keep the existing
+++++++++++++++++++ connection alive.
+++++++++++++++++++--------------------------------------------------------
| FUZZ | used in test blocks to insert a fuzzy string. the test
+++++++++++++++++++ will be executed for each possible fuzz string that could
+++++++++++++++++++ be inserted. this means for every literal and sequence, you
+++++++++++++++++++ will get a copy of the test with all instances of FUZZ
+++++++++++++++++++ replaced.
+++++++++++++++++++--------------------------------------------------------
| %FUZZ | used in test blocks to insert the length of the fuzz string
+++++++++++++++++++ in ascii form. IE: if the fuzz length is 4, the system will
+++++++++++++++++++ insert the ascii character "4".
+++++++++++++++++++--------------------------------------------------------
| %%FUZZ | as above, except inserts the binary length. currently, this
+++++++++++++++++++ is done as 4byte value (or sizeof(size_t) on your platform)
+++++++++++++++++++--------------------------------------------------------
| |X=[off:len:def]| Indicates a variable whose contents derive from the
+++++++++++++++++++ preceding packets' data. off is the offset into the
+++++++++++++++++++ previous packet, len is the length of data, and def is
+++++++++++++++++++ a default value (usually for the first packet).
+++++++++++++++++++--------------------------------------------------------
| $X=y | used to create a symbol, with name X and value y. this will
+++++++++++++++++++ replace each occurance of X in the fuzzing payload with y.
+++++++++++++++++++ additionally, all instances of %X would become strlen(y)
+++++++++++++++++++ ex: FUZZ X would become FUZZ y, and FUZZ %X would become
+++++++++++++++++++ FUZZ 1 (since y is 1 character).
+++++++++++++++++++--------------------------------------------------------
| $X[N]=y | used to create an array (or block) of symbols. N represents
+++++++++++++++++++ an index into the array. This replacement happens prior to
+++++++++++++++++++ the FUZZ replacement, and will cause replacement N times
+++++++++++++++++++ for each array.
+++++++++++++++++++--------------------------------------------------------
| !X=deadbeef | Used to create a binary subsitution symbol. The first
+++++++++++++++++++ occurance of X within the fuzz payload will become the
+++++++++++++++++++ binary bytes defined by deadbeef. Valid formats for
+++++++++++++++++++ specifying binary data:
+++++++++++++++++++ !X=de ad 0xbe Efca \xfe BADCab
+++++++++++++++++++--------------------------------------------------------
| !X[N]=deadbeef | Used to create an array (or block) of binary symbols. N
+++++++++++++++++++ represents an index into the array. NOTE: the symbol size
+++++++++++++++++++ could vary here - a length limiting option is in the works
+++++++++++++++++++--------------------------------------------------------
| ++X | Special flag for binary symbols that will attempt to
+++++++++++++++++++ increment the start value after every fuzz case. NOTE:
+++++++++++++++++++ the engine tries to be "intelligent" about incrementing,
+++++++++++++++++++ but for symbol values larger than 4 bytes, or symbols on
+++++++++++++++++++ big endian machines, there may be errors resulting.
+++++++++++++++++++--------------------------------------------------------
|-"reserved words"| The following fuzz case keywords are considered special
+++++++++++++++++++ cases and may not be used as symbols (or undefined behavior
+++++++++++++++++++ will occur:
+++++++++++++++++++ __SEQUENCE_NUM_ASCII__ - This keyword only applies to
+++++++++++++++++++ sequences and will increment after each sequence
+++++++++++++++++++ addition where it is replaced. (ex: if you have
+++++++++++++++++++ a sequence defined as AAA__SEQUENCE_NUM_ASCII__
+++++++++++++++++++ and a max sequence length of 100, you'll get
+++++++++++++++++++ AAA0001AAA0002AAA0003... etc).
+++++++++++++++++++--------------------------------------------------------
caveat: all config files MUST end with a newline.
chapter 3 - my little fuzzer, first time out
so, lets take the above knowledge and build a simple little fuzzing test.
==========================================================================
# begin my first fuzzing test.
# some literals to fuzz around with
literal=abcdefg
literal=hijklmn
literal=opqrstu
literal=vwxyz01
literal=2345678
literal=9.,/-()
# some sequences - these get expanded
sequence=%n
sequence=%%n
sequence=a
sequence=A
sequence=abacabb
sequence=12345678987654321
#how big to expand sequences
maxseqlen=1024
#this is going to be a simple fuzz, so just put the word FUZZ as a test
#after endcfg, then follow that with -- and a newline
endcfg
FUZZ
--
========================================================================
save the above snippet to '/tmp/myfirst.cfg'
then run:
sfuzz -O -f /tmp/myfirst.cfg
and check your output.
now modify some more. the line where you have 'FUZZ' change to
[FUZZ} this crap
save and rerun. see the difference? play around with it. add second test by
putting the following after the --
this is not a fuzz. sad face.
--
remember, newline is important at the end of the file.
chapter 4 - fuzzy wuzzy gets around
so, now to use on network host. lets say we have a webserver running on
foo.com and it has some etc enumeration vulnerability. we can use fuzzer to
find this out. in the above, add the following to the config portion of the
file:
# etc enumeration
literal=./../../../etc/
# wait 200ms between requests
reqwait=200
this will cause the system to pause when doing network outputs for 200ms
between each request. (note : the system will already pause for 100ms to wait
for data which may be returned on the socket).
now, we add a test case to the bottom:
GET /FUZZ HTTP/1.1
Hostname: foo.com
--
it is important that in this test case, we make sure those lines become
terminated with CRLF (i didn't do that in this example). since the webserver
won't read it right without them(although, maybe that's a good fuzz test).
anyway, to run, simply change the cmd line now to:
sfuzz -T -f /tmp/myfirst.cfg -S foo.com -p 80
and fire it off. use a network monitor to watch the traffic. there is a
rudimentary 'test for response' in there which dumps the response to the
screen, but it's not terribly reliable.
!!!!!!!! SUPER LARGE DISCLAIMER !!!!!!!!!!!!
don't use this to exploit someone's network, or be a douche. this is for
security research use and internal testing. using this to crash someones system
without permission or "pwn sum n00bz" is pretty lame.
thats all for now