как защититься от LDAP Injection

Мы создаем приложение, которое использует LDAP через php, и я подумал, можно ли что-нибудь сделать с внедрением в LDAP, и еще лучше, как защититься от внедрения LDAP?


person Chris    schedule 18.08.2010    source источник


Ответы (5)


При создании фильтров 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);
    }
}
//[...]
person Stefan Gehrig    schedule 19.08.2010
comment
Как мне дезинфицировать пароль, поскольку эти специальные символы разрешены? - person Bastien974; 22.01.2013
comment
Это именно то, что делает приведенный выше код... он превращает специальные символы и кодирует их. Это похоже на URL-адреса, представьте, если кто-то поместит & в параметр, и вы его конвертируете. Тот факт, что пароль браузера/ldap является разумным и пытается исправить эту ошибку для вас, не означает, что по-прежнему можно отправлять специальные символы. - person TravisO; 16.03.2016
comment
Пробовал это решение, и оно не работает должным образом. Пришлось заменить массив шестнадцатеричных символов на: array(\x5c,\x2a,\x28,\x29), чтобы заставить его работать. - person Kevin Roth; 03.05.2017
comment
@KevinRoth: Это невозможно. array("\x5c", "\x2a", "\x28", "\x29") фактически совпадает с array('\\', '*', '(', ')'), в то время как RFC2254 требует, чтобы эти символы были заменены на '\5c', '\2a', '\28' и '\29' буквально. - person Stefan Gehrig; 03.05.2017
comment
Я вижу, что вы говорите. Возможно, то, что я пытаюсь сделать, отличается от ОП. После выполнения ldap_search я выполняю ldap_bind для аутентификации. Когда я заменяю символы в пароле пользователя, привязка возвращает false. Возможно, мне не следует заменять символы в пароле, используя этот метод? Как еще можно защититься от инъекции в пароль? Спасибо! - person Kevin Roth; 03.05.2017
comment
@KevinRoth: Да, вы не должны заменять символы в пароле, используемом для привязки к LDAP. Это экранирование просто должно произойти, когда вы создаете фильтры LDAP для запросов, чтобы избежать LDAP-инъекций (это LDAP-эквивалент SQL-инъекций). - person Stefan Gehrig; 03.05.2017

Один момент, который следует учитывать, заключается в том, что привязка LDAP с именем пользователя (DN), но без пароля, считается анонимной привязкой. Поэтому вам следует проверить, могут ли переданные учетные данные связываться через LDAP для проверки пользователя, если они передают пустой пароль, а вы передали его как есть, вы можете ввести кого-то неправильно.

person geoffc    schedule 18.08.2010
comment
Спасибо, это я понимаю, и на самом деле это не инъекция. - person Chris; 20.08.2010
comment
@Chris: Согласен, это не совсем инъекция, но в рамках того же основного проблемного пространства. - person geoffc; 20.08.2010
comment
Прочитав этот ответ, я сразу же протестировал приложение, которое мы разрабатываем, и эта конкретная проблема не была обнаружена, спасибо! - person Crazy Joe Malloy; 14.12.2011

В PHP 5.6+ вы должны использовать функцию ldap_escape для значений фильтра. и РДН. Такие как:

// 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)";
person ChadSikorra    schedule 30.06.2016

В большинстве случаев для LDAP используется учетная запись только для чтения. Поскольку LDAP плохо записывает, обновления происходят только в очень небольших разделах приложения, где можно использовать другую учетную запись.

Даже в этом случае язык запросов и язык обновления полностью разделены.

Чтобы защититься от отображения нежелательной информации, рассматривайте все вводимые пользователем данные как испорченные и убедитесь, что испорченные данные никогда не используются, прежде чем они будут проанализированы, очищены, должным образом экранированы и скопированы в чистую переменную.

Точно так же вы можете выбрать только те данные, которые вы ожидаете от ответа, и вернуть их для отображения.

person Peter Tillemans    schedule 18.08.2010
comment
Чтобы защититься от отображения нежелательной информации, рассматривайте все вводимые пользователем данные как испорченные и убедитесь, что испорченные данные никогда не используются, прежде чем они будут проанализированы, очищены, должным образом экранированы и скопированы в чистую переменную. как бы это сделать, вот в чем вопрос? - person Chris; 19.08.2010

person    schedule
comment
Хотя этот код может дать ответ на вопрос, предоставление дополнительного контекста относительно того, как и/или почему он решает проблему, улучшит долгосрочную ценность ответа. - person Peter Gordon; 30.06.2016