Protos

Protos is a suite of security tools developed at the University of Oulu in Finland. They provide tools to test the DNS, HTTP client, SNMP, WAP, LDAP, ISAKMP, H225, and SIP implementations. The test tools and white papers on black-box security testing are available at http://www.ee.oulu.fi/research/ouspg/protos.

Codenomicon (http://www.codenomicon.com) is a company that provides the same type of test tools that Protos does, but for many additional protocols. It can be considered a commercial version of Protos.

All test tools come in a similar form. They test a client and/or a server implementation by sending malformed request/replies. While this section focuses on DNS, most of the explanations apply to other Protos testing suites.

The details of the DNS tests are displayed at http://www.ee.oulu.fi/research/ouspg/protos/testing/c09/dns/index.html. The DNS suite consists of a Java program that generates DNS requests to test a DNS server, DNS replies, and zone transfers to test a DNS client, and it also contains a DNS proxy written in Python. So it can be run on any platform that runs Python and Java, including Windows, Linux, Mac OS X, BSD, and Solaris.

The Java test tools handle TCP connections only, but a lot of DNS client/servers handle UDP only. This is why Protos provides the tool udpproxy, which translates UDP packets to TCP connections.

Let's take a look at the Protos DNS server. It is used to test a DNS client implementation. On the server, run the DNS server:

$ java -jar c09-dns-response-r1.jar
20061103 10:31:43 PROTOS c09-dns-response test tool
(http://www.ee.oulu.fi/research/ouspg/protos/testing/c09/dns/)
20061103 10:31:43 Created with Codenomicon Mini-Simulation Toolkit 1.2
20061103 10:31:43 Licensed for use in Oulu University Secure Programming Group.
Distribution strictly prohibited.
20061103 10:31:43 options:
20061103 10:31:43 Test suite c09-dns-response-r1.jar: PROTOS c09-dns test suite
20061103 10:31:43 TEST CASE #0 (c09-dns-response-r1.jar)
20061103 10:31:47 Listening for TCP connections to port 53...

Tip

The server used to run the Protos DNS server should not already be running a DNS server. If it is, you need to turn it off during the tests.

Run the UDP proxy on the same server as the Protos DNS server:

$ python.exe udpproxy.py

On the client under test, send a query to the Protos DNS server. Under Linux, you can use dig to send queries to a specific DNS server:

[julien@asus ˜]$ dig @192.168.1.101 protos1

; <<>> DiG 9.3.2 <<>> @192.168.1.101 protos1 ; (1 server found) ;;
global options:  printcmd ;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20516 ;; flags: qr aa ra;
QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;protos1.                       IN      A

;; ANSWER SECTION:
protos.invalid.         65535   IN      A       127.0.0.1

;; Query time: 1035 msec
;; SERVER: 192.168.1.101#53(192.168.1.101) ;; WHEN: Fri Nov  3 10:39:02 2006 ;;
 MSG SIZE  rcvd: 55

Warning

Use a unique hostname for each request; otherwise, dig could use its DNS cache instead of sending the query to the test tool.

On the server, you see the UDP request being translated to a TCP stream to the server:

2006-11-03T10:38:47.723000 received udp request of length 25 from 192.168.1.100:
33293
2006-11-03T10:38:49.516000 reading dns packet of len 55 from tcp socket
2006-11-03T10:38:49.516000 end-of-file receiving tcp message from test tool
2006-11-03T10:38:49.516000 did tcpquery
2006-11-03T10:38:49.516000 send 55 to 192.168.1.100 ...
2006-11-03T10:38:50.467000 sending via udp since tcp connection was refused
2006-11-03T10:38:50.467000 sent tcp reply of length 55

And the server receiving the request:

20061103 10:38:48 Connected to 127.0.0.1 port 1982, local port 53
20061103 10:38:49 port 53 <-- 127.0.0.1 port 1982 27 octet(s)
20061103 10:38:49 port 53 --> 127.0.0.1 port 1982 57 octet(s)
20061103 10:38:49 Closing connection to 127.0.0.1 port 1982
20061103 10:38:49 delay of 1000 ms...
20061103 10:38:50 Test case #0 completed
20061103 10:38:50 TEST CASE #1 (c09-dns-response-r1.jar)
20061103 10:38:52 Listening for TCP connections to port 53...

Some replies are malformed, and the client may complain:

;; Got bad packet: bad label type
54 bytes
0f 54 84 80 00 01 00 01 00 00 08 70 72 6f 74 6f
73 34 36 00 00 01 00 01 06 70 72 6f 74 6f 73 07
69 6e 76 61 6c 69 64 00 00 01 00 01 00 00 ff ff 00 04 7f 00 00 01 ;;
Got bad packet: FORMERR
56 bytes
48 47 84 80 00 01 00 01 00 00 00 00 08 70 72 6f
74 6f 73 34 37 00 00 01 00 01 06 70 72 6f 74 6f
73 07 69 6e 76 61 6c 69 64 00 00 00 00 01 00 00 ff ff 00 04 7f 00 00 01

There are 11,138 tests for the client. A quick way to run all of them with dig is:

[julien@asus ˜]$ for N in 'seq 1 11138'; do dig @192.168.1.101 protos$N; done

For each test, you should check whether the client behaves correctly. For example, you can monitor:

  • Memory and CPU usage. If a server reply requires too much memory on CPU cycles, an attacker could create a denial of service.

  • Crashes or freezes.

  • Corruption of the client. You can query a normal DNS server to make sure the DNS client still behaves correctly.

  • The uptime of the underlying OS to verify that the machine did not reboot.

  • The duration of the query. If it takes longer than usual, an attacker could make the client unavailable to other users.

In the same way, you can use the Protos DNS client to test a server. If the DNS server handles UDP connections only, you need to run udpproxy.py on the Protos client server, and run tcproxy.py on the DNS server being tested:

$ java -jar c09-dns-query-r1.jar --host domain.net
20061103 17:37:53 PROTOS c09-dns-query test tool
(http://www.ee.oulu.fi/research/ouspg/protos/testing/c09/dns/)
20061103 17:37:53 Created with Codenomicon Mini-Simulation Toolkit 1.2
20061103 17:37:53 Licensed for use in Oulu University Secure Programming Group.
Distribution strictly prohibited.
20061103 17:37:53 options: --host domain.net
20061103 17:37:53 Test suite c09-dns-query-r1.jar: PROTOS c09-dns test suite
20061103 17:37:53 TEST CASE #0 (c09-dns-query-r1.jar)
20061103 17:37:53 Connecting to domain.net TCP port 53
20061103 17:37:53 port 4031 --> 192.168.0.1 port 53 38 octet(s)
20061103 17:37:53 port 4031 <-- 192.168.0.1 port 53 249 octet(s)
20061103 17:37:53 Closing connection to 192.168.0.1 port 53
20061103 17:37:53 delay of 1000 ms...
20061103 17:37:54 Test case #0 completed
20061103 17:37:54 TEST CASE #1 (c09-dns-query-r1.jar)
[...]

There are 10,460 tests to run. You can specify which tests to launch:

$ java -jar c09-dns-query-r1.jar --host domain.net-index 1,3,5,6-25,30-

The zone-transfer test is done the same way as the DNS server test:

$ java -jar c09-dns-zonetransfer-r1.jar --host domain.net

Protos created similar test suites for HTTP replies, WAP, SIP, SNMP, LDAP, H225, and ISAKMP. These test cases are well appreciated in the network security industry; most vendors integrated them into their QA cycle.

The challenge with this tool is to isolate the test that created a crash or an anomaly on the target. Most of the time, you have to write a custom script for each device to test, which is not an easy job. Mu Security (http://www.musecurity.com) has developed an appliance that does all this work. It tests all the corner cases for a lot of protocols, such as Protos, and can also identify exactly which packet crashed the device or created a peak in CPU or memory usage, and so on. It is not free like Protos, but it can save a lot of time by avoiding the need for custom automation.

—Julien Sobier