• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 解剖WIN2K下的空會話

    發表于:2007-05-25來源:作者:點擊數: 標簽:
    I、 Introduction II、 About TCP port 445 III、The null session IV、 Break through "RestricAnonymous=1" V、 Conclusion 終于有時間可以寫自己的東西了。呵呵,直入主題,不廢話了。 I、 Introduction 關于WIN2K下面的空會話,已經是一個很老的話題了。

    I、 Introduction
    II、 About TCP port 445
    III、The null session
    IV、 Break through "RestricAnonymous=1"
    V、 Conclusion

    終于有時間可以寫自己的東西了。呵呵,直入主題,不廢話了。

    I、 Introduction

    關于WIN2K下面的空會話,已經是一個很老的話題了。當然,也一直被認為是WIN2K自帶的一個后門。當建立一個空會話之后,對于一臺配置不到位的WIN2K服務器來說,那么將能夠得到非常多的信息,比如枚舉帳號等等。


    II、 About TCP port 445, WIN2000的TCP 445端口

    SMB(Server Message Block)協議在NT/2000中用來作文件共享,在NT中,SMB運行于NBT(NetBIOS over TCP/IP)上,使用137,139(UDP),139(TCP)端口。在2000中,SMB可以直接運行在tcp/ip上,而沒有額外的NBT層,使用TCP 445端口。因此在2000上應該比NT稍微變化多一些。

    可以在“網絡連接/屬性/TCPIP協議/屬性/高級/WINS中設置啟用或者禁用NBT(NetBIOS over TCP/IP)。

    當2000使用網絡共享的時候,就面臨著選擇139或者445端口了。下面的情況確定會話使用的端口:

    1、如果客戶端啟用了NBT,那么連接的時候將同時訪問139和445端口,如果從445端口得到回應,那么客戶端將發送RST到139端口,終止這個端口的連接,接著就從445端口進行SMB的會話了;如果沒有從445端口而是從139得到回應,那么
    就從139端口進行會話;如果沒有得到任何回應,那么SMB會話失敗。
    2、如果客戶端禁用了NBT,他就將只從445端口進行連接。當然如果服務器(開共享端)沒有445端口進行SMB會話的話,那么就會訪問失敗了,所以禁用445端口后,對訪問NT機器的共享會失敗。
    3、如果服務器端啟用NBT,那么就同時監聽UDP 137、138端口和TCP139,445。如果禁用NBT,那么就只監聽445端口了。

    所以對于2000來說,共享問題就不僅僅是139端口,445端口同樣能夠完成。


    III、The NULL session,關于空會話

    NULL會話(空會話)使用端口也同樣遵循上面的規則。NULL會話是同服務器建立的無信任支持的會話。一個會話包含用戶的認證信息,而NULL會話是沒有用戶的認證信息,也就好比是一個匿名的一樣。

    沒有認證就不可能為系統建立安全通道,而建立安全通道也是雙重的,第一,就是建立身份標志,第二就是建立一個臨時會話密匙,雙方才能用這個會話進行加密數據交換(比如RPC和COM的認證等級是PKT_PRIVACY)。不管是經過NTLM還是經過Kerberos認證的票據,終究是為會話創建一個包含用戶信息的令牌。(這段來自Joe Finamore)

    根據WIN2000的訪問控制模型,對于空會話同樣需要提供一個令牌。但是空會話由于是沒有經過認證的會話,所以令牌中不包含用戶信息,因此,建立會話雙方沒有密匙的交換,這也不能讓系統間發送加密信息。這并不表示空會話的令牌中不包含SID,對于一個空會話,LSA提供的令牌的SID是S-1-5-7,這就是空會話建立的SID,用戶名是 ANONYMOUS LOGON。這個用戶名是可以在用戶列表中看到的。但是是不能在SAM數據庫中找到,屬于系統內置的帳號。
    (關于這部分對NULL SESSION的分析,可以參照:《NULL Sessions In NT/2000》http://rr.sans.org/win/null.php)

    NULL會話幾乎成為了微軟自己安置的后門,但是微軟為什么要來設置這樣一個“后門”呢?我也一直在想這個問題,如果NULL會話沒有什么重要的用途,那么微軟也應該不會來設置這樣一個東西。好不容易才在微軟上找到這個:

    當在多域環境中,要在多域中建立信任關系,首先需要找到域中的PDC來通過安全通道的密碼驗證,使用空會話能夠非常容易地找到PDC,還有就是關于一些系統服務的問題。而且LMHOSTS的#Include就需要空會話的支持,可以參考文章:
    http://support.microsoft.com/default.aspx?scid=kb;EN-US;q121281
    還有http://support.microsoft.com/default.aspx?scid=kb;EN-US;q124184

    其實建立一個空會話的條件也非常嚴格。首先要能夠滿足上面的,也就是打開TCP 139和TCP 445端口。我們可以從一次關閉這兩個端口的情況中看得出來。服務器關閉445和139端口,然后我們來進行空會話的連接。首先,客戶端打算
    連接的是445端口,然后再試圖連接139端口。當然最后還是失敗了。
    僅僅開放這兩個端口還不行,服務器還必須得打開IPC$共享。如果沒有IPC共享,即使共享一個文件,有權限為Anonymous Logon,也不能建立會話,即使權限設置為完全控制,出現的連接錯誤依然是權限不夠。這和其他帳號是不一樣的。如果要允許一個文件夾共享能夠類似IPC$(命名管道而非共享)能夠使用空會話,那么需要修改注冊表:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters\中的:NullSessionShares,
    添加新的共享名,這樣才能建立一個共享的空會話。這時,將不依賴IPC的存在了。(即使這樣的空會話對于后面的突破也是一點沒可取之處的,因為沒有了IPC$命名管道,RPC不可取了,這下知道IPC這個命名管道的具體實現了。呵呵)

    雖然空會話建立的要求很嚴格,但是那都是默認建立的。既然是默認的,對于使用WIN2K系統的服務器來說,就還是有利用的價值。最明顯的就是空會話可以很方便地連接到其他的域,枚舉用戶、機器等。這也就是掃描軟件進行探測的原理。我舉個簡單的程序例子來說明這個用途,并枚舉用戶組和用戶。

    #include <windows.h>
    #include <stdio.h>
    #include <lm.h>

    #pragma comment (lib, "Mpr.lib")
    #pragma comment (lib, "Netapi32.lib")

    void explorer_groups(char *);

    void main( int argc, char *argv[ ] )
    {
    DWORD ret;
    char username[100] = "", password[100] = "";
    char server[100] = "", ipc[100] = "";
    NETRESOURCE NET;

    if (argc == 1) {
    exit(1);
    }

    strncpy(server,argv[1],100);
    printf("server: %s\n", server);

    sprintf(ipc,"\\\\%s\\ipc$",server);

    NET.lpLocalName = NULL;
    NET.lpProvider = NULL;
    NET.dwType = RESOURCETYPE_ANY;
    NET.lpRemoteName = (char*)&ipc;

    printf("setting up session... ");
    ret = WNetAddConnection2(&NET,(const char *)&password,(const char *)&username,0);

    if (ret != ERROR_SUCCESS)
    {
    printf("IPC$ connect fail.\n");
    exit(1);
    }
    else printf("IPC$ connect suclearcase/" target="_blank" >ccess.\n");
    explorer_groups((char*)&server);

    printf("Disconnect Server... ");
    ret = WNetCancelConnection2((char*)&ipc,0,TRUE);
    if (ret != ERROR_SUCCESS)
    {
    printf("fail.\n");
    exit(1);
    }
    else printf("success.\n");
    exit (0);
    }

    void explorer_groups(char *server)
    {
    DWORD ret, read, total, resume = 0;
    int i;
    LPVOID buff;
    char comment[255];
    wchar_t wserver[100];

    do {
    ret = NetLocalGroupEnum(wserver, 1, (unsigned char **)&buff, MAX_PREFERRED_LENGTH, &read, &total, &resume);

    if (ret != NERR_Success && ret != ERROR_MORE_DATA)
    {
    printf("fail\n");
    break;
    }
    PLOCALGROUP_INFO_1 info = (PLOCALGROUP_INFO_1) buff;

    for (i=0; i<read; i++) {
    printf("GROUP: %S\n",info[i].lgrpi1_name);

    WideCharToMultiByte(CP_ACP, 0, info[i].lgrpi1_comment , -1, comment,255,NULL,NULL);
    printf("\tCOMMENT: %s\n",comment);

    DWORD ret, read, total, resume = 0;
    ret = NetLocalGroupGetMembers((const unsigned short*)&wserver, info[i].lgrpi1_name, 2, (unsigned char **)&buff, 1024, &read, &total, &resume);

    if (ret != NERR_Success && ret != ERROR_MORE_DATA) {
    printf("fail\n");en
    break;
    }

    PLOCALGROUP_MEMBERS_INFO_2 info = (PLOCALGROUP_MEMBERS_INFO_2) buff;

    for (unsigned i=0; i<read; i++) {
    printf("\t\t%S\n", info[i].lgrmi2_domainandname);
    printf("\t\t\tSID:%d\n", info[i].lgrmi2_sid);
    printf("\t\t\tSIDUSAGE:%d\n",info[i].lgrmi2_sidusage);
    }
    NetApiBufferFree (buff);
    }

    NetApiBufferFree (buff);

    } while (ret == ERROR_MORE_DATA );
    }

    這是一個簡單的例子。當然可以查詢更多的東西。類似,就不再重復了。枚舉用戶名是很重要的用途,因為接下來可以做的就是進行密碼的猜解,這對系統安全構成的威脅是非常大的。

    想到有威脅,就需要知道怎么防范。防范很簡單。不過這里需要提醒的是關于注冊表(或者安全策略中)中可以設置Restrictanonymous為1,這樣可以禁止空連接進行枚舉。因為很多安全配置介紹中都是這樣做的,因為如果設置為2的
    話,有一些問題會發生。比如一些WIN的服務出現問題等等。但是,RestricAnonymous設置為1并不會組織用戶帳號的枚舉。因為空連接是一樣能夠建立的,并不是說阻止了空連接的建立。但是我們這里需要來突破??!


    IV、 Break through "RestricAnonymous=1",突破RestricAnonymous=1的限制進行用戶枚舉

    雖然我們還是能夠建立空連接,但是卻沒有那些NET函數的訪問權限了。這個可以看MSDN上關于對網絡管理函數的安全問題。但是,有一個突破點,呵呵,那就是猜測。這個需要聯系到訪問控制模型上了。就象前面對NULL會話說到的那樣,NULL會話獲得ANONYMOUS LOGON 用戶名的SID(安全標志符),系統用SID來標志這個用戶,同時創建令牌。而這個令牌才是系統對用戶的訪問權限標志,并不是用帳戶名來確定?,F在我們需要的是SID,因為令牌中包含了帳戶的SID,對于系統來說,SID是不變的。SID是在帳戶或者組創建的時候就建立好了??墒敲總€WIN2K系統為相同用戶名的帳戶創建的SID并不相同。

    我們來先分析這個重要的SID。SID的格式是:S-R-X-Y(1)-Y(2)-……-Y(N)。其中S表示該字符串是SID,R是SID的版本號,對于2000來說,這個就是1,然后X是標志符的頒發機構 (identifier authority)。對于2000內的帳戶,頒發機構就是NT,值是5。然后Y表示一系列的子頒發機構,前面幾項是標志域的,最后一個Y(N)標志著域內的帳戶和組。也就是說,對于多數帳戶來說,區別在與這個Y(N)。

    現在需要分析一下SAM結構中對帳戶的管理。展開注冊表的SAM之后,
    HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Builtin\Aliases\Members,存儲著重要的帳戶內容。找到本地的域,然后展開,得到的就是本地帳號的所有SID列表。分析其規律,因為有些是系統規定的Y(N),所以就有規律了。其中的000001F4,十進制的500,這一定是一個固定的,標志系統建立時候的內置管理員帳號administrator,000001F5就是GUEST帳號了。然后看到了一個跳躍到了000003E8,這是其他帳號的開始,比如 TsInternetUser帳戶以及自定義的帳戶了。

    到了這里,我們還需要函數的支持。LookupAccountName()和LookupAccountSid(),這兩個函數是允許空會話使用的。上面通過空會話來建立連接然后使用NET*函數枚舉帳戶已經被RestrictAnonymous禁止了。因此,SID成為我們的突破口。不過SID對于一臺機器來說是固定的,但是并不是說跟其他的機器的SID是一樣的,我們需要進行一定的猜測,用來獲得SID中不同的部分,就是幾個子頒發機構。哈哈,我們猜測的東西就是用戶名。假象系統存在的用戶名,比如TsInternetUser,Guest帳戶等。然后通過這些帳戶名獲得SID的前面部分,然后根據前面部分進行枚舉,將最后一個子頒發機構進行遞加,從而獲得每個帳戶的SID,然后又回過來,利用函數LookupAccountSid()進行用戶名的查詢。這樣就達到了枚舉帳戶的目的了,而且是在 RestrictAnonymous=1 的情況下。

    我寫了一個程序,我猜測的帳號是guest。大致思路在這里介紹了,把代碼貼在這里太占篇幅,原代碼和執行程序可以在我的主頁(www.opengram.com)下載。


    V、 Conclusion

    不過,即便我們花費這么大精力能夠突破RestricAnoymous=1的限制,但是防范起來簡直太容易了。取消掉IPC$命名管道,就讓NULL SESSION完全沒有用了。



    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>