7

I'm currently using Sulley to fuzz my FTP server, but I'm having problems. I want to specify the STRU command, which has a syntax:

STRU [<SP> F|R|P] <CRLF>

I tried to specify the optional F,R,P arguments to the STRU command like the following:

s_initialize('DataSTRU')
s_static('STRU ')
s_group('struv', values=['F', 'R', 'P'])
s_block_start('strub', group='struv')
s_block_end()
s_repeat('strub', min_reps=0, max_reps=1, fuzzable=True)
s_static('\r\n')

This sends the right commands to the FTP server (STRU F; STRU R; STRU P), but the problem is that is it. It doesn't try to omit the character or fuzz it, which I would also like. I know I can just specify the argument to fuzz, but I would like to fuzz the argument as well as mutate the valid arguments. Any ideas how to apply the optional+fuzzable argument to the above code?

Another problem is that I don't know how can I check which command is currently being used - I'm using the commands inside s_block_start and I'm iterating through the s_group element like the following:

s_initialize('DataSet')
s_group('commands', values=['MODE', 'PROT', 'STRU'])
s_block_start('DataBlock', group='commands')
s_delim(' ')
  // TODO: how to check whether:
  // if   [current_command == 'MODE'] do this
  // elif [current_command == 'PROT'] do this
  // else [current_command == 'STRU'] do this
s_static('\r\n')
s_block_end()

That's it. Any ideas and recommendations are welcome. Thanks

alcor
  • 111
  • 5
eleanor
  • 528
  • 2
  • 5
  • 11

1 Answers1

4

Since both of your questions relate to groups, we should look at how they're used first. The purpose is to bind block data to a set of static values -- sulley iterates through the list of values and generates block data for each one.

The example in the docs uses HTTP, where the block data is a simple HTTP request and the group values are HTTP verbs ('GET', 'POST', 'PUT', etc). In the example, sulley generates and fuzzes the data block (the request) for each HTTP verb in the s_group:

# define a new block named "HTTP BASIC".
s_initialize("HTTP BASIC")

# define a group primitive listing the various HTTP verbs we wish to fuzz.
s_group("verbs", values=["GET", "HEAD", "POST", "TRACE"])

# define a new block named "body" and associate with the above group.
if s_block_start("body", group="verbs"):
    # break the remainder of the HTTP request into individual primitives.
    s_delim(" ")
    s_delim("/")
    s_string("index.html")
    s_delim(" ")
    s_string("HTTP")
    s_delim("/")
    s_string("1")
    s_delim(".")
    s_string("1")
    # end the request with the mandatory static sequence.
    s_static("\r\n\r\n")
# close the open block, the name argument is optional here.
s_block_end("body")

From the doc:

When this defined request is loaded into a Sulley session, the fuzzer will generate and transmit all possible values for the block "body", once for each verb defined in the group

Now for the first question, you're getting only the 'STRU F' 'STRU R' and 'STRU P' strings because each value in the list supplied to s_group() is treated the same as a string created with s_static() -- they aren't mutated.

You can try this:

s_initialize('DataSTRU')

for op in ['', 'F', 'R', 'P']:      # trying to include your missing-arg case
  s_block_start('stru-%s' % op)
  s_static('STRU')
  s_delim(' ')
  s_string(op)
  s_static('\r\n')
  s_block_end()

Which is closer to what you were aiming for, but you can probably get away with just this:

s_initialize('DataSTRU')
s_block_start('stru')
s_static('STRU')
s_delim(' ')
s_string('F')
s_static('\r\n')
s_block_end()

Which fuzzes the space (s_delim()) and the parameter (s_string()).

For your second question, you don't need to check which command is being used. If the blocks are specific to a command, just define them separately:

s_initialize('DataSet')
s_block_start('mode')
s_static('MODE')
# MODE-specific primitives 
s_block_end()
s_block_start('prot')
s_static('PROT')
# PROT-specific primitives
s_block_end()
for op in ['', 'F', 'R', 'P']:
  s_block_start('stru-%s' % op)
  s_static('STRU')
  s_delim(' ')
  s_string(op)
  s_static('\r\n')
  s_block_end()
jma
  • 309
  • 1
  • 2