Анализатор обнаружил, что для формирования выражения на языке XPath используются непроверенные данные из внешнего источника. Это может стать причиной возникновения XPath-инъекции.
Уязвимости, связанные с инъекциями, относятся к категории A03:2021 – Injection списка OWASP Top 10 Application Security Risks.
Рассмотрим пример:
class UserData
{
HttpRequest request;
XPathNavigator navigator;
void RetrieveUserData()
{
string username = request.Form["username"];
string password = request.Form["password"];
string hashedPassword = Hash(password);
string query = $@"//users/user[
username/text() = '{username}' and
passwordHash/text() = '{hashedPassword}']
/data/text()";
object res = navigator.Evaluate(query);
....
}
}
В этом примере XPath-выражение используется для получения данных пользователя из XML-файла. Имя пользователя хранится "как есть", а пароль хранится в зашифрованном виде.
Злоумышленник может передать в качестве имени пользователя и пароля любые данные. Проверка будет скомпрометирована, если во входных данных передать выражение, которое сделает XPath-условие всегда истинным. Так как пароль хранится в зашифрованном виде, то внедрять опасное выражение нужно вместе с именем пользователя.
Для примера пусть имя пользователя будет 'john'. Добавим к нему выражение такого вида:
' or ''='
Вместо пароля может быть введён любой набор символов. Тогда XPath-выражение будет иметь такой вид:
[
username/text()='john' or ''='' and
passwordHash/text() = '750084105bcbe9d2c89ba9b'
]
Теперь выражение содержит оператор 'or'. Рассмотрим, как оно вычисляется:
Таким образом, результатом XPath-запроса будут данные пользователя 'john' независимо от того, правильный пароль был введён или нет. Это может привести к утечке данных.
Не следует использовать непроверенные внешние данные в XPath-выражениях. Для повышения безопасности стоит экранировать потенциально опасные символы во внешних данных. Примерами таких символов являются "<", ">" и "'". Экранирование может быть произведено с помощью метода 'SecurityElement.Escape':
class UserData
{
HttpRequest request;
XPathNavigator navigator;
void RetrieveUserData()
{
string username = request.Form["username"];
string password = request.Form["password"];
username = SecurityElement.Escape(username);
string hashedPassword = Hash(password);
string query = $@"//users/user[
username/text()= '{username}' and
passwordHash/text() ='{hashedPassword}']
/data/text()";
object res = navigator.Evaluate(query);
....
}
}
Существуют другие возможности для предотвращения XPath-инъекций. Например, Microsoft предлагает возможность реализации класса-резолвера. Его можно использовать в методах класса 'XPathNavigator', которые принимают строку XPath-выражения и объект, реализующий интерфейс 'IXmlNamespaceResolver'.
Это позволяет определить свои собственные переменные и функции внутри XPath-выражения, которые будут обработаны резолвером. Само по себе это не является решением проблемы XPath-инъекции, но определение своиx переменных позволяет использовать подход, похожий на параметризацию SQL-запросов.
Также анализатор считает источниками небезопасных данных параметры методов, доступных из других сборок. Более подробно эта тема раскрыта в заметке "Почему важно проверять значения параметров общедоступных методов". Рассмотрим пример:
public class UserData
{
XPathNavigator navigator;
public object RetrieveUserData(string username,
string password)
{
string hashedPassword = Hash(password);
string query = $@"//users/user[
username/text()= '{username}' and
passwordHash/text() = '{hashedPassword}']
/data/text()";
return EvaluateXpath(query);
}
private object EvaluateXpath(string xpath)
{
object res = navigator.Evaluate(xpath);
....
}
}
В этом примере метод 'RetrieveUserData' доступен из других сборок. Параметры этого метода 'username' и 'password' не проверяются перед внедрением в XPath-запрос. Полученное выражение в переменной 'query' передаётся в метод 'EvaluateXpath', где используется без проверки. В таком случае анализатор выдаст предупреждение с низким уровнем достоверности.
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.). |
Данная диагностика классифицируется как:
|