2007-07-21

What happened to tcp flag URGENT, MSG_OOB and SIGURG?

Nobody today uses tcp urgent mode, so it's good topic to make some research on.

Usually when socket receives tcp packet with URG flag it treats it as normal tcp data. recv() is going to read urgent data as it was normal tcp stream. The only difference is that the last byte of data is discarded. The last byte in urgent data was always a problem due to incoherent rfc.

Pseudocode for this case:

server: send("ab", MSG_OOB)
client: recv() -> "a"
Tcp urgent packets whould trigger SIGURG for process that's listening on socket. It doesn't work until we set process pid of socket owner (thanks MichaƂ for this tip).
if (fcntl(sd, F_SETOWN, getpid()) < 0) {
perror("fcntl()");
exit(-1);
}
The interesting thing is that after we enabled SIGURG it's possible to send a signal to remote process without sending any valid data. Such situation occures when process receives tcp URG packet with one byte payload. The only byte is discarded, no data is waiting on a socket, but SIGURG is sent to a process.
client: signal(SIGURG, handler);
client: fcntl(sd, F_SETOWN, getpid());
client: poll([sd], 1, 1000);
server: send("a", MSG_OOB);
client: signal SIGURG is received by a handler
client: poll ends, because of received signal
client: but there aren't any data waiting on a socket
That's all. Feel free to use draft source code of client and server I used for testing.


2007-07-18

Peek at new nmap-nse scripts

Well. I'll give you a peek at my new scripts for nmap. This scripts aren't public yet, I hope this post will give mi motivation to finish them.

This time we're going to focus on traceroute. New traceroute function in nmap looks like this:

# ./nmap -n -sS -p80 scanme.insecure.org --traceroute

TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 0.33 (censor)
2 7.93 (censor)
3 ...
4 7.84 212.76.35.50
5 23.85 212.76.35.58
6 4.90 212.76.35.177
7 5.06 217.6.51.49
8 209.72 62.154.5.9
9 191.55 64.125.12.169
10 196.77 64.125.26.26
11 198.69 64.125.28.142
12 200.40 208.185.168.173
13 200.15 205.217.153.62

My first script gives similar results. It works almost like standard traceroute, but instead of sending Syn packets with small ttl, it injects packets to established connection. The idea is stolen from Lcamtuf's 0trace tool.
# ./nmap -n -sS -p80 --script=0trace.nse scanme.insecure.org -P0
Interesting ports on 205.217.153.62:
PORT STATE SERVICE
80/tcp open http
|_ 0trace:
(censor)
(censor)
?
212.76.35.50
212.76.35.58
212.76.35.177
217.6.51.49
62.154.5.9
64.125.12.169
64.125.26.26
64.125.28.142
208.185.168.173
205.217.153.62

Next script is quite different. It sends Syn packet with Record Route ip option (see ping -R). Note that this time ip addresses are different than in previous scans. That's because routers have several ip addresses and Record Route records ip from outgoing interface (I think). The disadvantage of this method is that it's possible to record only nine hops.
# ./nmap -n -sS -p80 --script=recordroute.nse scanme.insecure.org -P0
Interesting ports on 205.217.153.62:
PORT STATE SERVICE
80/tcp open http
|_ record route:
(censor)
(censor)
212.76.35.49
212.76.35.57
212.76.35.178
217.6.51.42
62.154.5.254
64.125.12.170
209.249.254.29


2007-07-15

Is it possible to abuse icmp?

I wonder what's going to happen when malicious user will inject crafted icmp packet with some error information (like Port Unreachable) to tcp connection. Will the connection be closed? You may think that to inject something like this it's needed to guess sequential numbers. That's not exactly correct. Icmp payload can be relatively small, specification says it has to carry at least 8 bytes from OSI 3th layer, so only tcp source and destination port must be included.

I can assume that you're going to use google. To block your connection I have to only send 65K packets with payload: from google, to you, from 80port to, and sequentially select your local port. I should guess after while. That's even less than 65K possibilities, on standard linux there are less than 32K possible local ports (see proc parameter ip_local_port_range).

The question is how common tcp stacks are interpreting such crafted Icmp message.

There are also other possibly vulnerable applications. For example most dns servers, to make recursive queries use source port 53 (see bind 'query-source address' option). How dns servers react for icmp errors with relatively small payload? Is it possible to perform Dos attack using this method?

UPDATE #1:
Well, of course port number in tcp header uses only 16 bits. So to 8 bytes in icmp payload should fit: source, destination port, seq number.

I change my question. How common tcp stacks interpret icmp packets with too short payload?

UPDATE #2:
Linux seems to be immune for this kind of attack. The function that parses icmp errors for tcp transmission is in linux/net/tcp_ipv4.c:tcp_v4_err(). The code says, that payload must be at least 8 bytes long. Source and destination port in the payload must be correct and sequence number must be in correct range. In other case icmp packet is simply dropped.