2

現在、Spring LDAP Filter クラスを使用するか、LdapEncoder.filterEncode() を使用して、フィルターを適切にエスケープしています。

同時に、WireShark を使用して、ローカル マシンと LDAP サーバーの間で交換されるパケットをキャプチャしています。

そして、私は問題を抱えているようです。適当に値をエスケープしても(デバッグで確認済み)、ネットワーク経由でエスケープされずに出てきます。また、値が javax.naming.InitialContext に入るまでずっとエンコードされていることを (デバッグを通じて) 確認しました。

以下に例を示します (Spring LDAP 1.3.0 を使用しており、これらは Oracle JDK 6u45 と Oracle JDK 7u45 の両方で発生することに注意してください)。

私自身のコードでは、サービス層で行われている呼び出しは次のとおりです。

     String lMailAddress = (String) ldapTemplate.searchForObject("", new EqualsFilter(ldapUserSearchFilterAttribute, principal).encode(), new ContextMapper() {
                @Override
                public Object mapFromContext(Object ctx) {
                    DirContextAdapter lContext = (DirContextAdapter) ctx;
                    return lContext.getStringAttribute("mail");
                }});

この時点で、フィルターの encode() メソッドによって返される文字列が "(sAMAccountName=boi\2a)" であることを確認できます。

コードをデバッグできる最後のポイントは次のとおりです (org.springframework.ldap.core.LdapTemplate の 229 行目から)。

SearchExecutor se = new SearchExecutor() {
            public NamingEnumeration executeSearch(DirContext ctx) throws javax.naming.NamingException {
                return ctx.search(base, filter, controls);
            }
        };

後で executeSearch() が呼び出されると、フィルター文字列に「(sAMAccountName=boi\2a)」が含まれていることも確認できます。

javax,naming.* または com.sun.jndi.ldap.* のソース コードがないため、これ以上デバッグすることはできません (com.sun.jndi.ldap.LdapCtx が呼び出されているため)。

ただし、executeSearch() から呼び出しが戻るとすぐに、WireShark は、フィルター「(sAMAccountName=boi*)」を含む searchRequest を含む LDAP パケットが送信されたことを通知します (* はエスケープされなくなりました)。

同様のエンコーディングを使用し、LdapTemplate のさまざまなメソッドを使用して、期待していた結果を得ました (エンコードされたフィルターが WireShark で送信されているのを見ました) が、公開したばかりの場合、値が送信される前にデコードされる理由を説明できません.

状況を理解するのを手伝ってください。残念ながら、私はここで LDAP プロトコルを正しく理解していません。

ありがとう。

免責事項:同じ質問を Spring LDAP フォーラムに投稿しました。

TL/DR: LDAP サーバーに送信する前に、com.sun.jndi.ldap.LdapCtx が LDAP エンコード フィルタ (\2a から * など) をデコードするのはなぜですか?

更新: IBM の J9 JDK7 で同じ動作を試してみました。

4

3 に答える 3

3

私は Spring LDAP に詳しくありませんが、必ずしも心配する必要があるようには思えません。LDAP フィルタは平文ではなく、バイナリ エンコーディングで送信されます。このメカニズムではエスケープする必要はありません (エスケープするのも正しくありません)。

「(sAMAccountName=boi*)」を例に取りましょう。書かれているように、このフィルターは "boi" の subInitial コンポーネントを持つ部分文字列フィルターです。ご指摘のとおり、部分文字列フィルターではなく等値フィルターにしたい場合は、文字列表現を "(sAMAccountName=boi\2a)" にする必要があります。ただし、これらのフィルターのバイナリ エンコーディングはエスケープを使用せず、代わりに ASN.1 BER タイプを使用して部分文字列フィルターと等価フィルターを区別します。

"(sAMAccountName=boi*)" を部分文字列フィルターとして使用する場合、エンコードされた表現は次のようになります。

 a417040e73414d4163636f756e744e616d6530058003626f69

一方、"(sAMAccountName=boi\2a)" を等価フィルターとして使用する場合、エンコーディングは次のようになります。

 a316040e73414d4163636f756e744e616d650404626f692a

エンコーディングの完全な説明は私が入りたいものではありませんが、最初の最初の "a4" はそれが部分文字列フィルターであることを示し、2 番目の最初の "a3" はそれが部分文字列フィルターであることを示します。等式フィルター。

WireShark で送信された実際のバイト数を確認できるはずです。文字列表現を生成するときに WireShark がフィルタを適切にエスケープしない可能性がありますが、これは WireShark 自体の問題です。ディレクトリ サーバーはバイナリ表現のみを取得し、LDAP サーバーがそれを誤解するとは考えにくいです。

于 2013-10-17T17:31:20.267 に答える
2

OWASP は、検索用に文字列をエンコードすることを提案しています。

public static final String escapeLDAPSearchFilter(String filter) {
   StringBuffer sb = new StringBuffer(); // If using JDK >= 1.5 consider using StringBuilder
   for (int i = 0; i < filter.length(); i++) {
       char curChar = filter.charAt(i);
       switch (curChar) {
           case '\\':
               sb.append("\\5c");
               break;
           case '*':
               sb.append("\\2a");
               break;
           case '(':
               sb.append("\\28");
               break;
           case ')':
               sb.append("\\29");
               break;
           case '\u0000': 
               sb.append("\\00"); 
               break;
           default:
               sb.append(curChar);
       }
   }
   return sb.toString();

}

DN 文字列は別の方法でエスケープされます。以下のリンクを参照してください。

https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java

于 2014-11-12T13:50:41.547 に答える
0

最良の方法は、パラメーター化されたフィルター検索方法を使用することです。これにより、パラメーターが適切にエンコードされます。

https://docs.oracle.com/javase/jndi/tutorial/ldap/search/search.htmlを参照してください

// Perform the search
NamingEnumeration answer = ctx.search("ou=NewHires", 
    "(&(mySpecialKey={0}) (cn=*{1}))",      // Filter expression
    new Object[]{key, name},                // Filter arguments
    null);                  // Default search controls
于 2022-01-07T12:34:50.670 に答える