How to: Fuzzing Web Services on IIS 6.0 and ASP.NET
14 Jan 2007
So we want to fuzz something SOAPy, again. Well here's how we're gonna do it. The approach I like to take with clients is a gray-box, or code-assisted penetration testing. Gray box analysis is a powerful technique combining input testing with source analysis, runtime tracing, profiling, and debugging to identify real issues in the software. In this example we're taking from the last post to fuzz or not to fuzz web services. So we've got web services in managed code plus some unmanaged code modules handing user-input.
SOAP fuzzing should begin by taking the client requests for each service and isolating the element values to be manipulated. In the first stage of fuzzing we will change the entire value, without conforming to the value format. This should turn up gross errors in the consumption of the web service data or denial of service conditions from unexpected data formats. In the second fuzzing sweep we'll present the value in the correct format, with just a portion of that value replaced with a malformed value. This phase should find issues that would pass a validation gateway, but still cause problems when the data is consumed.
In all fuzzing cases we will start from a perspective of a most-correct request, where only a single value is fuzzed, before fuzzing multiple values concurrently. Additional phases will be specific tests based on a deep understanding of the logic being tested, such as fuzzing a value that states
For example, during phase one everything between the Value tags should be fuzzed as a single blob. The string “
In phase two, the value will be separated into its subcomponents. For each subcomponent a fuzzed value will be inserted until all portions of the value are individually fuzzed.
And to keep it going, fuzzing should actually be expanded quite a bit beyond the example above. In addition to fuzzing strings with other strings, INT’s should used, byte arrays, etc. Also, the separator values (e.g. : and / and =) should also included in testing. Typical payloads used in fuzzing are shown below. When testing we usually apply the relevant selection to the logic being tested.
To monitor the behavior of the web service during the fuzzing runs we attach WinDbg to the worker process with heap checking enabled. We break on any significant exceptions to investigate the call stack and relevant code sections. The event log is scrubbed for any reported errors, which are then investigated. To determine denial of service conditions we use Perfmon to observe the process's CPU and memory usage. In our SOAP fuzzing we should also insert a unique marker into each request, and also log each sent request, so that we can later reproduce the condition that caused the error. In this case we will place an incremented number in the User Agent value of the SOAP requests, which is readable in the IIS logs. In addition, the randomness of fuzzing could be seeded with a value which would allow for reproducibility. This is possible with some of the fuzzing frameworks out there, we we haven't talked about too much, such as Peach.
SOAP fuzzing should begin by taking the client requests for each service and isolating the element values to be manipulated. In the first stage of fuzzing we will change the entire value, without conforming to the value format. This should turn up gross errors in the consumption of the web service data or denial of service conditions from unexpected data formats. In the second fuzzing sweep we'll present the value in the correct format, with just a portion of that value replaced with a malformed value. This phase should find issues that would pass a validation gateway, but still cause problems when the data is consumed.
In all fuzzing cases we will start from a perspective of a most-correct request, where only a single value is fuzzed, before fuzzing multiple values concurrently. Additional phases will be specific tests based on a deep understanding of the logic being tested, such as fuzzing a value that states
UserID=5
, with a range of integers.For example, during phase one everything between the Value tags should be fuzzed as a single blob. The string “
org:division/category/DATA=DATA
” will be replaced as a whole with the fuzz strings.Original | <Value>org:division/category/DATA=DATA</Value> |
Fuzzed | <Value>AAAAAAAAAAAAAAAAAAAAAA</Value> |
In phase two, the value will be separated into its subcomponents. For each subcomponent a fuzzed value will be inserted until all portions of the value are individually fuzzed.
Original | <Value>org:division/category/DATA</Value> |
Fuzzed #1 | <Value>AAAAAAAAA:division/category/DATA=DATA</Value> |
Fuzzed #2 | <Value>org:AAAAAAAAAAAA/category/DATA=DATA</Value> |
Fuzzed #3 | <Value>org:division/AAAAAAAAAAAAA/DATA=DATA</Value> |
Fuzzed #4 | <Value>org:division/category/AAAAAAAAAA=DATA</Value> |
Fuzzed #5 | <Value>org:division/category/DATA=AAAAAAAAAA</Value> |
And to keep it going, fuzzing should actually be expanded quite a bit beyond the example above. In addition to fuzzing strings with other strings, INT’s should used, byte arrays, etc. Also, the separator values (e.g. : and / and =) should also included in testing. Typical payloads used in fuzzing are shown below. When testing we usually apply the relevant selection to the logic being tested.
- Character multiples
- Max unsigned and signed integer values
- Variations on format strings using '%n'
- Long strings
- Empty strings and null values
- Extended ASCII
- Binary values
- Base64 and HTML encoded values
- SQL Injection
- Common bad ASCII (' " < >)
- All numbers
- All letters
- All spaces
- Invalid date formats
- Dictionaries relevant to the application
To monitor the behavior of the web service during the fuzzing runs we attach WinDbg to the worker process with heap checking enabled. We break on any significant exceptions to investigate the call stack and relevant code sections. The event log is scrubbed for any reported errors, which are then investigated. To determine denial of service conditions we use Perfmon to observe the process's CPU and memory usage. In our SOAP fuzzing we should also insert a unique marker into each request, and also log each sent request, so that we can later reproduce the condition that caused the error. In this case we will place an incremented number in the User Agent value of the SOAP requests, which is readable in the IIS logs. In addition, the randomness of fuzzing could be seeded with a value which would allow for reproducibility. This is possible with some of the fuzzing frameworks out there, we we haven't talked about too much, such as Peach.
Saam Choy
2007-09-10T08:21:22.000Z
A lot of what you are talking about is automated by tools like WSBang and OWASP's WSFuzzer. They do a great job of auto-generating massive, and in some cases intelligent, attack vectors.
Chris Weber
2007-09-20T08:51:40.000Z
Absolutely, we leverage those tools quite a bit. Not the one's you've mentioned specifically, but usually we build from frameworks such as Peach as I mentioned. I often find the WS I'm dealing with have too many complexities that are more easily tested this way. The canned WS fuzzing tools are usually fine for simple web services though. Although I argue that there's only a few specific areas where fuzzing managed code is even useful.