代码之家  ›  专栏  ›  技术社区  ›  Chris

如何防止LDAP注入

  •  8
  • Chris  · 技术社区  · 14 年前

    我们正在构建一个通过PHP使用LDAP的应用程序,我想您是否可以对LDAP中的注入做些什么,更好的方法是如何防止LDAP注入?

    5 回复  |  直到 7 年前
        1
  •  9
  •   Stefan Gehrig    14 年前

    在构造LDAP筛选器时,必须确保根据 RFC2254 :

    任何带有ACII的控制字符 代码<32以及字符 在LDAP过滤器中具有特殊意义 “*”,“(”,“)”和“\”(反斜杠) 转换为表示形式 反斜杠后面跟着两个十六进制 表示十六进制的数字 字符的值。

    Zend_Ldap 例如,使用以下例程

    //[...]
    $val = str_replace(array('\\', '*', '(', ')'), array('\5c', '\2a', '\28', '\29'), $val);
    for ($i = 0; $i<strlen($val); $i++) {
        $char = substr($val, $i, 1);
        if (ord($char)<32) {
            $hex = dechex(ord($char));
            if (strlen($hex) == 1) $hex = '0' . $hex;
            $val = str_replace($char, '\\' . $hex, $val);
        }
    }
    //[...]
    
        2
  •  2
  •   geoffc    14 年前

    要考虑的一个项目是,具有用户名(DN)但没有密码的LDAP绑定被视为匿名绑定。因此,如果您测试通过的凭证是否可以通过LDAP绑定来验证用户,如果他们传递了一个空密码,并且您按原样传递了它,那么您可能会错误地让某人进入。

        3
  •  2
  •   ChadSikorra    7 年前

    在php 5.6+中,应该使用 ldap_escape 用于筛选值和RDN的函数。例如:

    // Escaping an LDAP filter for ldap_search ...
    $username = ldap_escape($username, null, LDAP_ESCAPE_FILTER);
    $filter = "(sAMAccountName=$username)";
    
    // Escaping a DN to be used in an ldap_add, or a rename...
    $rdn = ldap_escape('Smith, John', null, LDAP_ESCAPE_DN);
    $dn = "cn=$rdn,dc=example,dc=local";
    

    此外,如果您在搜索中接受属性名的用户输入,那么您应该验证它是可接受的OID或属性名。您可以使用这样的函数:

    /**
     * Validate an attribute is an OID or a valid string attribute name.
     *
     * @param string
     * @return bool
     */
    function isValidAttributeFormat($value)
    {
        $matchOid = '/^[0-9]+(\.[0-9]+?)*?$/';
        $matchDescriptor = '/^\pL([\pL\pN-]+)?$/iu';
    
        return preg_match($matchOid, $value) 
            || preg_match($matchDescriptor, $value);
    }
    
    $attribute = 'sAMAccountName';
    $value = 'foo';
    
    if (!isValidAttributeFormat($attribute)) {
        throw new \InvalidArgumentException(sprintf('Invalid attribute name: %s', $attribute));
    }
    
    $value = ldap_escape($value, null, LDAP_ESCAPE_FILTER);
    $filter = "($attribute=$value)";
    
        4
  •  1
  •   Peter Tillemans    14 年前

    在大多数情况下,它使用的是LDAP的只读帐户。由于LDAP的写操作能力较差,因此只能在应用程序的很小的部分中使用其他帐户进行更新。

    即使这样,查询语言和更新语言也是完全分离的。

    为了防止显示不需要的信息,请将所有用户输入视为污点,并确保在分析、清理和正确转义污点数据并将其复制到一个干净的变量之前,永远不要使用污点数据。

    类似地,您可能只考虑从响应中选择期望的数据,并将其返回以进行显示。

        5
  •  0
  •   Eugene    8 年前
    function ldap_quote($str) {
        return str_replace(
                array( '\\', ' ', '*', '(', ')' ),
                array( '\\5c', '\\20', '\\2a', '\\28', '\\29' ),
                $str
        );
    }