3

使用 LDAP 協定驗證 AD 帳號密碼

 1 year ago
source link: https://blog.darkthread.net/blog/auth-with-ldap/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用 LDAP 協定驗證 AD 帳號密碼

2023-02-22 11:25 PM 0 742

除了使用 IIS 整合驗證跟呼叫 Windows API,.NET 還有一種流傳甚廣的 LDAP 帳號密碼驗證程式寫法:

var username = "Child\\someone";
var password = "P@ssW0rd";
// web Domain DC = 10.0.0.7
// child Domain DC = 10.0.0.6
var ldapPath = "LDAP://10.0.0.7";
AuthByLdap();

void AuthByLdap()
{
    try
    {
        Console.WriteLine($"Connect {ldapPath} with {username}...");
        DirectoryEntry entry = new DirectoryEntry(ldapPath, username, password);
        // Bind NativeAdsObject 時將觸發身分驗證
        object obj = entry.NativeObject;
        Console.WriteLine("Login Successful");

        // 執行到此沒出錯即代表帳號密碼有效,以下加碼搜尋 AD 所有名為 someone 的項目
        DirectorySearcher search = new DirectorySearcher(entry);
        // 搜尋 AD 帳號名稱為 someone 的項目 (child 跟 web 網域各有一位)
        search.Filter = "(SAMAccountName=someone)";
        foreach (SearchResult r in search.FindAll())
        {
            Console.WriteLine(r.Properties["distinguishedName"][0].ToString());
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Login failed: " + ex.Message);
    }
}

面對這段程式碼,我有幾個疑問:

  1. 在 AD 架構中,DC 就是 LDAP 主機,若套用前幾天跨子網域登入 IIS的情境。 我是否可以用 child\someone 登入 web LDAP 主機(DC)?
  2. 若可以用 child\someone 登入網域 web LDAP,過程需要連到網域 child LDAP 嗎?
  3. DC 主機若具有 GC 角色,同時提供 389 (LDAP) 及 3268 (GC) 兩種 Port,LDAP 協定可選擇其一連接,依先前 PowerShell Get-ADUser/C# 跨網域搜尋 AD 帳號使用 3268 可跨網域搜索,在這段程式是否也會產生相同差異?

現在來一一驗證。先說測試環境:

  • 程式在 10.0.0.8 主機上執行,機器加入 web 網域,以 web\someone 登入 Windows 執行程式
  • web 網域 DC/LDAP 伺服器 IP = 10.0.0.7
  • child 網域 DC/LDAP 伺服器 IP = 10.0.0.6
  • web 網域與 child 網域都有一個名為 someone 的使用者

測試四次:

  1. 使用 web\someone 連 LDAP://10.0.0.7
    成功登入,查到 web 的 someone
  2. 使用 child\someone 連 LDAP://10.0.0.7
    成功登入,查到 web 的 someone
  3. 使用 web\someone 連 GC://10.0.0.7
    成功登入,查到 web 跟 child 的 someone
  4. 使用 child\someone 連 GC://10.0.0.7
    成功登入,查到 web 跟 child 的 someone

Fig1_638126764446553109.png

使用 Wireshark 觀察封包,發現 .NET DirectoryEntry 底層是用 NTLMSSP Challenge/Response 完成認證,不需要直接傳輸密碼,而第 15 列 NTMLSSP_NEGOTIATEsasl 的 SASL 及第 17 列的 GSS-API(整合 Kerberos) 都是 LDAP 協定的安全認證框架。參考

Fig2_638126764449118308.png

既然是用 NTLM,web DC (10.0.0.7) 便能直接驗證跨網域的 child\someone 帳號,不需接觸 child DC (10.0.0.6),就 bindResponse success:

Fig3_638126764451665840.png

將 LDAP://10.0.0.7 改成 GC://10.0.0.7,封包過程幾乎一模一樣,只差在連接埠由 389 Port 變成 3268 Port,而查詢對象為 GC,故可查到 web 跟 child 的 someone 共兩筆:

Fig4_638126764454486794.png

那如果將 GC://10.0.0.7 改成 GC://web.contoso.com,會跟 IIS 一樣改用 Kerberos 嗎?會!

此時 10.0.0.8 會與 child DC 10.0.0.6 建立 CLDAP (UDP 389 Port) 及 KRB5 (88 Port) 連線:

Fig5_638126764459810121.png

不過我的環境疑似 DNS SPN 沒設好,出現 KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 錯誤,最後仍是走 NTLM: 參考

Fig6_638126764462512158.png

依據微軟文件,當條件被滿足時,AD DS 是可以支援 Kerberos 的,至於是哪裡沒設好?感覺愈游水愈深,這段就先不深究了,容我游回岸邊喘一會兒。

最後做個小結:

  1. 使用 DirectoryEntry 連線 AD DC/LDAP 主機時,在 Bind 階段會觸發帳號驗證,類似 IIS 可協商使用 NTLM 或 Kerberos。
  2. 若走 NTLM,由 DC 直接驗證跨網域帳號;當條件滿足時則會啟動 Kerberos,此時客戶端需連跨網域 DC 的 LDAP (389 UDP) 及 Kerberos (88 TCP)。
  3. DC 同時支援 389 及 3268,ldap:// 預設連 389、gc:// 預設連 3268,前者只能搜覽自己網域的項目,但資訊較完整;後者可查詢全網域所有物件,但屬目錄性質,完整資料需接洽該網域 DC 取得。

Experimenets about athenticating cross-domain account with AD DS.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK