Tshark can help us greatly to audit applications that make use of sockets. Furthermore, we can use it as a support tool to understand and investigate protocols that lack technical documentation. In this recipe we will see a couple of examples that represent these scenarios.
Suppose that we are auditing a small application that uses sockets to communicate with clients. The application itself only receives a series of commands and replies to them with some information. Let's see how it works:
bmerino@Mordor:~$ nc 192.168.1.35 8012 Service BANE-1.0 IP --> 192.168.1.35 PORTS --> 8012,8080,80,21 AAAA --->Command not found. Type H for help H --->H,IP,PORTS,TCP,UDP,LISTENING,CONNECTIONS
So, when sending a series of requests from netcat (client), we received information about the network configuration of the server. When we sent the AAAA instruction, the server did not recognize it and sent Command not found. Type H for help to us. To test the stability of the application, we will create the following script in python to fuzz the application and detect this way any server error (buffer overflow, integer overflow, and so on).
What we do with this script is to send lots of packets to the server using a malformed payload to verify that the server validates inputs correctly. To do this we will use the fuzzing capabilities of Scapy.
Before launching the script we will leave Tshark running to save all traffic generated by the client and server. Then we run the following command:
bmerino@Mordor:~$ ./fuzzer.py 192.168.1.35 8012 Sending Data <rest of output omitted>
After a few seconds, the script exits with the following message:
Traceback (most recent call last): File "./fuzzer.py", line 13, in <module> streamFuzzer.send(packetFuzzer) File "/usr/lib/python2.7/dist-packages/scapy/supersocket.py", line 34, in send return self.outs.send(sx) socket.error: [Errno 104] Connection reset by peer
So, it appears that the server crashed when trying to process a certain type of payload. To identify the exact packet that generated this crash we will use the pcap file we created to store the communication. Since each of the packets sent to the server contains random values, we will look for the last Command not found server reply:
bmerino@Mordor:~$ tshark -r fuzz.pcap -R 'tcp contains "Command not"' | tail -1
This would generate the following output:
386 121.861764000 192.168.1.35 -> 192.168.1.42 TCP 101 8012 > 52567 [PSH, ACK] Seq=491 Ack=296 Win=16896 Len=35 TSval=578987 TSecr=1369935
According to the previous output, the frame 386 was the last response from the server to some unknown command. It is likely, therefore, that a subsequent packet generated the crash. Let's see the last packet sent by the server:
bmerino@Mordor:~$ tshark -r fuzz.pcap -T fields -e frame.number -e tcp.flags -R "ip.src == 192.168.1.35" | tail -1 418 0x0010
As we see, it makes sense. It seems that, after sending frame 386, the server received another packet which was confirmed with an ACK (
0x0010
). However, the payload of that packet resulted in a server crash, closing this way the socket. To identify which was the packet that caused the crash, we will use thetcp.analysis.acks_frame
filter of frame 418. This value will tell us which frame this ACK was sent to:bmerino@Mordor:~$ tshark -r fuzz.pcap -T fields -e tcp.analysis.acks_frame -R "frame.number==418"
This gave the following output for me:
416
Now that we know the packet that caused the crash, we can dump it into a file and replicate the crash with the help of a debugger to research the vulnerability in more depth.
bmerino@Mordor:~$ tshark -r fuzz.pcap -x -R "frame.number==417" | grep ^0 | awk -F " " '{print $2}' | tr -d " \n"
This would generate the following output:
78929c89b9de0013e8f626ef0800450000440c0940004006ab0dc0a8012ac0a80123cd571f4c13a678046e5c996b80180391c7d200000101080a0014e74 0008ccab666ac3b16c6b666a61666b61c3b1660a
Here's another quick example. Occasionally, we may find that Tshark cannot interpret certain protocols. For instance, if we analyze a proprietary protocol and Tshark does not have its dissector we would only see the raw payload. However, this may sometimes provide us with clues about the behavior of the application. The output that follows shows an extract of traffic generated between a client (192.168.254.221) and a server (192.168.254.220) using an unknown protocol. The payload sent by the client represents a login attempt against the server. The server response is made up of a set of bytes whose meaning is unknown to us. Take a look at the following screenshot:
However, after trying many login attempts with different users and passwords and observing the server responses, we could infer when the user exists in the database. Although all logins were unsuccessful, when we used the admin user one of the bytes of the response was totally different from the rest of replies. Thanks to this, we could make a little script to get valid users from the server based on that set of bytes.
bmerino@Mordor:/tmp$ tshark -r appA.pcap -T fields -e frame.number -e data.data "tcp.srcport==8882 && data.data" 6 00:00:aa:aa:0a:00:00:aa:aa:a1:aa:aa:aa:aa:aa:aa:aa 9 00:00:aa:aa:0a:00:00:aa:aa:a1:aa:aa:aa:aa:aa:aa:aa 12 00:00:aa:aa:0a:00:00:bb:aa:a1:aa:aa:aa:aa:aa:aa:aa 15 00:00:aa:aa:0a:00:00:aa:aa:a1:aa:aa:aa:aa:aa:aa:aa 18 00:00:aa:aa:0a:00:00:aa:aa:a1:aa:aa:aa:aa:aa:aa:aa bmerino@Mordor:/tmp$ tshark -r appA.pcap -R frame.number==11 -x | grep '<.*>' -m 1 0060 30 30 30 30 7e 7e 3c 61 64 6d 69 6e 3e 7c 7c 7c 0000~~<admin>|||