ONC-RPC program fuzzer design and specification
Version 0.1--ONLY TESTED ON RedHat 7.3, but should compile elsewhere
Dominique Brezinski	8/2002

Required parameters:
	-h <Target Host> <-s and/or -a>
	-s      Test a specific RCP program 'n' [requires -v, and -p]
	-a      Test all registered RPC programs

Optional arguments:
	-v <Program Version>
	-p <protocol number, 17 for UDP or 6 for TCP>
	-i <n>  Do 'n' fuzzed messages per procedure
	-l <n>  'n' is last procedure to test
	-f <n>  'n' is first procedure to test
	-r <n>  Push 'n' random xdr items onto the SPIKE

Program Flow:
Start-->
	Parse arguments-->fail with usage message if required args not present
	Store endpoint information in target program list
	Do RPC endpoint information queries-->
		If -s then do PMAPPROC_GETPORT-->warn if unsuccessful
		If -a then do PMAPPROC_DUMP and store results in target program list
	Target program test loop, for each target program in list-->
		Generate valid ONC-RPC header for program
		Procedure test loop, for each procedure in test range-->
			Procedure test loop 1, n times-->
				Generate ONC RPC record frame if TCP, sometimes lie about
					frame length
				Generate valid or invalid auth and valid verifier
				Generate random (fuzzed) procedure arguments
				Send message
				Optional: Receive response, parse, and print
			End procedure test loop 1
	End target program test loop
Finish

Reproduction of a given test run:
	Sunrpcfuzz uses rand() for all random value generation.  srand() is seeded with getpid(), but if the environment variable "RANDVAL" is present then call atoi() to convert the value specified in RANDVAL into an integer to seed srand().  This allows for test run duplication since rand() is a deterministic PRNG.  If a test run induces a bug in the server, note the value used to initialize random, which is printed to stdout, and export the the environment variable RANDVAL with the initializer value.  Re-run sunrpcfuzz with the same commandline, and it should reproduce the test input that caused the bug.

For each iteration of test message for a given RPC program procedure, sunrpcfuzz does the following:

-Creates a random RPC message XID based on rand() output
-If the communication protocol is TCP, then it creates the record frame header.  4 out of 5 messages the record frame length specifier has the correct length value.  1 out of 5 messages specifies the length as the output of rand() modulus 65536.
-Creates a valid RPC Call message header using the generated XID and specifing the RPC program number, program version, and procedure number we are currently testing.
-Alternates between AUTH_NONE and AUTH_SYS authentication headers.  The AUTH_SYS headers use the output of rand() for the "timestamp" field, the client hostname, the output of getuid(), the output of getgid(), and a list of one alternate GID (GID 0).  The only exception to this is that the second message using AUTH_SYS contains a hostname that is too long (512 byte string of "%n" repeated).  This is done to test for buffer overflows or format string specifier bugs in client hostname handling.
-Creates a valid VERIFIER_NONE verifier block
-3 out of 4 messages include 1 to 'n' (derived through an equation that uses rand() as a variable and 'n' as an upper bound) random XDR components in the procedure argument portion of the RPC Call message.  The specifics of these random XDR components can be seen in the function s_onc_push_random_xdr_thing() in spike_oncrpc.c.  1 out of 4 messages include 0 to 99 (choosen by rand() % 100) of random bytes (generated using rand()) as the procedure arguments.

Using sunrpcfuzz to test RPC server programs:
	Sunrpcfuzz is a structured random input tester for ONC (Sun) RPC server programs.  This form of test tool is also known commercially as a fault-injector and in the security community as a "fuzzer."  The idea is to create input for the program being tested that is structured well-enough to be processed or partially processed (syntactically reasonably formed), but random, unexpected, and sometimes totally wrong in content (semantically incorrect).  This approach has proven effective in uncovering many bugs, often exploitable security vulnerabilities.
	Sunrpcfuzz does not test procedure 0, the NULL procedure, of RPC programs by default.  One can use the "-f" and "-l" options to specify the first procedure number and last procedure number to test respectively.  Simply specify "-f 0" to include the NULL procedure in a test run.  Otherwise, sunrpcfuzz will iterate through the procedures starting at 1 and ending at the hardcoded default (200) of the number specified with the "-l" option.  The "-i" option controls the number of test input messages created and sent by sunrpcfuzz.  The default number of test messages is 31, but it is beneficial to run with a much higher iteration value: in the 100-500 range is good, but obviously the test run will take much longer.
	Using the "-s" option allows for only testing a specific RPC program, in which case the program version and protocol that it is listening on must be specified with "-v" and "-p."  Using "-a" will cause sunrpcfuzz to send a DUMP query to the target server's Portmapper, and will store the results of the DUMP query in a list.  The results include all the RPC server programs registered with the Portmapper on the server, their version numbers, and the protocols that the specific version are listening on.  Sunrpcfuzz will then iterate through the list testing each procedure, as described previously, for every program version and protocol.
	The "-r" option allows the user to specify the upper bound of the number of random XDR component blocks that are placed in the procedure argument list for each test message.  The default is 5, which is normal sufficient.  However, it is worth while executing a test run with "-r 10" on occasion.  If the RPC program being tested has procedures that take long argument lists, then by all means specify an upper bound that is a few greater than the longest valid argument list implemented in a procedure.
