2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

深入探索MS SQL Server 2000網(wǎng)絡(luò)連接的安全問題

 duduwolf 2005-09-25
創(chuàng)建時(shí)間:2001-11-13
文章屬性:原創(chuàng)
文章來源:refdom
文章提交:refdom (refdom_at_263.net)

作者:refdom (refdom@263.net)

    下面我們要說的,并不是SQL Server存在的漏洞,而只是一些安全缺陷,存在一些問題,當(dāng)然這些問題是SQL Server一產(chǎn)生的時(shí)候就存在的。

1、MS SQL Server的密碼明文傳輸缺陷

   很倒霉,我沒有在微軟發(fā)布SQL Server的時(shí)候做下面的分析。當(dāng)我吃驚地發(fā)現(xiàn)SQL Server竟然是使用明文進(jìn)行密碼傳輸?shù)臅r(shí)候,我就馬上去查閱是否有這些資料??上б呀?jīng)早早有人提出能夠用sniffer獲取SQL Server的密碼了。不過,既然微軟這么大膽,我們還是去看看,分析分析這個缺陷。

    當(dāng)然,SQL Server的連接過程還是先進(jìn)行TCP連接的三次握手,同服務(wù)器建立連接過后,然后進(jìn)行TDS(tabular data stream)協(xié)議的數(shù)據(jù)交流,可惜的是我一直沒有找到TDS協(xié)議的具體描述,只有一些片段,所以,都只能一點(diǎn)點(diǎn)地對著數(shù)據(jù)報(bào)分析。誰有TDS協(xié)議(SQL Sevrer)的具體描述一定送我一份哦。

    直接到login包吧,你會發(fā)現(xiàn),你的用戶名完全是明文的,而密碼還不是。當(dāng)你改變密碼的時(shí)候,你可以看出,相同字符的編碼是一樣的,密碼字符之間用一個相同的字符作為分隔“a5”。呵呵。所以,最傻的辦法就是我做的這樣,一個字符一個字符地改變密碼,然后得到所有字符的對應(yīng)編碼(我不會解密)。
我使用的是SQL Server 2000 。我這里列舉一部分得到的對應(yīng)編碼。大家可以很容易得到完整的字符編碼。
“a”——b3          “A”——b1
“b”——83          “B”——81
“c”——93          “C”——91
“d”——e3          “D”——e1
“e”——f3          “E”——f1
    等等。

    對了,在SQL Server中不支持用 ‘、" 等等符號作為密碼,如果你在用這些字符作為密碼的話,那就糟糕了,你永遠(yuǎn)也登陸不上了,除非更改密碼。
    在TDS數(shù)據(jù)報(bào)的頭中規(guī)定了一個字節(jié)來表示數(shù)據(jù)報(bào)類型,我探測到的是0x10,而我得到的資料說是用0x02來表示Login的數(shù)據(jù)報(bào),可能是MS SQL Server在協(xié)議上有一些改動,因?yàn)镾ybase也是使用的TDS協(xié)議的,那么Sybase可能也是使用的明文傳輸吧,我手里沒有Sybase。可惜沒有TDS協(xié)議的完整描述,所以,我也偷懶沒有寫出專門獲得SQL Server賬號和密碼的sniffer程序,誰能給我TDS協(xié)議的詳細(xì)描述,請email: refdom@263.net。

    不過MS對SQL Server的傳輸還是提供加密辦法的,你可以使用SSL來加密。于是我也試了試,可以在實(shí)例屬性的網(wǎng)絡(luò)配置里面選擇強(qiáng)制協(xié)議加密,然后要求你重新啟動SQL Server,呵呵,然后呢,你啟動起來了么?哈哈,我可是吃了虧的。因?yàn)闆]有SSL證書,所以,你一啟動就錯誤,事件日志中說明是沒有提供有效的證書。重新安裝吧。該死的MS也不在我選擇的時(shí)候提醒一下。

    嗅探得到數(shù)據(jù)庫賬號意味著什么?如果能夠得到SA賬號呢?哈哈,有興趣可以看看我前些天寫的《從IIS轉(zhuǎn)到SQL數(shù)據(jù)庫安全》。


2、明文的數(shù)據(jù)傳輸缺陷
    如果沒有使用加密的協(xié)議的話,那么整個數(shù)據(jù)庫的網(wǎng)絡(luò)數(shù)據(jù)都是沒有加密的,而且是明文傳輸。無論是從客戶端發(fā)送命令還是從服務(wù)器端得到結(jié)果,都是明文傳輸?shù)???磥?,如果你用加密的協(xié)議,微軟是不會為你做任何安全防護(hù)的。我想,目前國內(nèi)使用的SQL Server數(shù)據(jù)庫差不多都是沒有使用SSL來加密,看來在網(wǎng)絡(luò)上能得到不少東西。


3、神秘的1434端口和服務(wù)器信息明文傳輸缺陷

    對于SQL Server2000來說,打開SQL Server客戶端準(zhǔn)備連接,當(dāng)拉開服務(wù)器列表的時(shí)候,整個局域網(wǎng)所有的SQL Server服務(wù)器都被列出來了。于是我發(fā)現(xiàn),從我自己的機(jī)器(192.168.0.1)上從1434端口廣播(192.168.0.255)了這個UDP包,然后,整個局域網(wǎng)中的SQL Server服務(wù)器都開始響應(yīng)這個UDP數(shù)據(jù)包,這時(shí),我的客戶端能夠得到所有服務(wù)器信息。

     這就是客戶端進(jìn)行連接的過程:當(dāng)客戶端連接到服務(wù)器時(shí),應(yīng)用程序請求連接遠(yuǎn)端計(jì)算機(jī),Dbnetlib.dll 將打開到連接中所指定的計(jì)算機(jī)網(wǎng)絡(luò)名上的 UDP 端口 1434 的連接。所有運(yùn)行 SQL Server 2000 的計(jì)算機(jī)都監(jiān)聽此端口。當(dāng)一個客戶端 Dbnetlib.dll 連接到該端口時(shí),服務(wù)器將返回一個監(jiān)聽服務(wù)器上運(yùn)行的所有實(shí)例的數(shù)據(jù)包。對于每個實(shí)例,該數(shù)據(jù)包報(bào)告該實(shí)例正在監(jiān)聽的服務(wù)器 Net-Library 和網(wǎng)絡(luò)地址。應(yīng)用程序計(jì)算機(jī)上的 Dbnetlib.dll 收到該數(shù)據(jù)包后,選擇在應(yīng)用程序計(jì)算機(jī)和 SQL Server 實(shí)例上都啟用的 Net-Library,然后連接為此數(shù)據(jù)包中的 Net-Library 列出的地址。

     通過1434端口傳輸特定的UDP數(shù)據(jù)包,然后服務(wù)器開始回應(yīng),所有這些都是明文傳輸?shù)?,我們可以很容易探測一個IP地址的1434端口,獲得該IP地址上運(yùn)行的SQL Server的相關(guān)信息。這些信息包括:主機(jī)名稱、實(shí)例名稱、版本、管道名稱以及使用的端口等。這個端口是微軟自己使用,而且不象默認(rèn)的1433端口那樣可以改變,1434是不能改變的,呵呵,那么我們?yōu)榱税踩?,去改變這個1433端口能起什么作用呢?

    我們可以來捕獲這些數(shù)據(jù)報(bào),可以發(fā)現(xiàn),通過1434端口的數(shù)據(jù)非常簡單,客戶端僅僅簡單地發(fā)送了02一個字節(jié)出去。不過多次捕獲,發(fā)現(xiàn)有時(shí)候發(fā)送的是 03。于是我就用下面程序一個一個測試,發(fā)送其他數(shù)據(jù)。不過最后只有02、03、04有回應(yīng)??磥磉@三種字節(jié)用來做SQL Server探測的。而且你可以發(fā)送 02 00 00,也可以發(fā)送 02 00 00 00 00等等都能夠得到SQL Server的回應(yīng),但是發(fā)送 02 03就不可以了。

    下面是一個利用1434進(jìn)行探測的程序,可以探測單個IP,也可以用來探測整個局域網(wǎng)的數(shù)據(jù)庫服務(wù)器。
////////////////////////////////////////////////////////////
//                                                   
// SQLPing by refdom
//
// Author: refdom. From Chip Andrews
// Email: refdom@263.net
//
////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <winsock2.h>

void decode_recv (char *buf, int size)
{
    int index;
    int counter = 0;

    for (index = 3; index < size; index++)
    {
        if ((buf[index] == ‘;‘) && (buf[index+1] != ‘;‘))
        {  
            //Look for a semi-colon and check for end of record (;;)
            if ((counter % 2) == 0)
            {
                printf(":");
                counter++;
            }
            else
            {
                printf("\n");
                counter++;
            }
        }
        else
        {
            if (buf[index] != ‘;‘)
            {  
                // If an end of record (;;), then double-space for next instance
                printf("%c",buf[index]);
            }
            else
            {
                printf("\n");
            }
        }
    }
      
    printf("\n");
}

void listen (void* v)
{
    static const unsigned int buffersize = 64000;
    static char buffer [buffersize];

    SOCKET s = (SOCKET)v;

    for (;;)
    {
        struct sockaddr_in udpfrom;
        int udpfromlen = sizeof(udpfrom);
        int n = recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&udpfrom, &udpfromlen);
        int e = WSAGetLastError();
        
        if (n > 0 && e == 0)
            decode_recv(buffer, n);

    }
}

void useage()
{
    printf("******************************************\n");
    printf("SQLPing\n");
    printf("\t Written by Refdom\n");
    printf("\t Email: refdom@263.net\n");
    printf("Useage: sqlping.exe target_ip \n");
    printf("*******************************************\n");
}

int main(int argc, char* argv[])
{
    WSADATA WSAData;
    SOCKET sock;
    SOCKADDR_IN addr_in;
    char buf[5]={‘\x02‘};
    HANDLE listener;

    useage();

    if (argc<2)
    {
        return false;
    }

    if (WSAStartup(MAKEWORD(2,0),&WSAData)!=0)
    {
        printf("WSAStartup error.Error:%d\n",WSAGetLastError());
        return false;
    }

    if ((sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET)
    {
        printf("Socket failed.Error:%d\n",WSAGetLastError());
        return false;
    }

    addr_in.sin_family=AF_INET;
    addr_in.sin_port=htons(1434);
    addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]);

    const int SNDBUF = 0;
    const int TCPNODELAY = true;
    const int BROADCAST = true;
    
    if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (const char*)&SNDBUF, sizeof(SNDBUF))==SOCKET_ERROR)
    {
        printf("Set SO_SNDBUF failed.Error:%d",WSAGetLastError());
        return false;
    }
    if (setsockopt(sock, SOL_SOCKET, TCP_NODELAY, (const char*)&TCPNODELAY, sizeof(TCPNODELAY))==SOCKET_ERROR)
    {
        printf("Set TCP_NODELAY failed.Error:%d",WSAGetLastError());
        return false;
    }
    if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&BROADCAST, sizeof(BROADCAST))==SOCKET_ERROR)
    {
        printf("Set SO_BROADCAST failed.Error:%d",WSAGetLastError());
        return false;
    }

    listener = (HANDLE) _beginthread(listen, 0, (void*)sock);

//    e = sendto(s, "\08", 1, 0,(sockaddr*) &hostaddr, sizeof(hostaddr));
    if (sendto(sock, buf, sizeof(buf), 0,(sockaddr*) &addr_in, sizeof(addr_in))==SOCKET_ERROR)
    {
        printf("Send failed.Error:%d\n",WSAGetLastError());
        return false;
    }

    printf("Listening....\n\n");

    // wait a little while for listener thread
    WaitForSingleObject(listener, 5000);

    WSACleanup();

    printf("SQLPing Complete.\n");
    return 0;
}

上面的程序只有探測作用,沒有破壞性。呵呵

     感謝Hectic給我提供的幫助。限于本人的水平,難免有錯誤之處,還請大家多多指正。如果誰有TDS協(xié)議(應(yīng)用在SQL Server上的)的具體描述手冊,請EMAIL給我,謝過了。EMAIL: refdom@263.net

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多