Предотвращение Команда Инъекциям Линии
в настоящее время мы создаем приложение, которое выполняет ряд внешних инструментов. Нам часто приходится передавать этим инструментам информацию, введенную в нашу систему пользователями.
очевидно, что это большой кошмар безопасности ждет, чтобы произойти.
к сожалению, мы еще не нашли классов в .NET Framework, которые выполняют программы командной строки, обеспечивая при этом такую же защиту от инъекционных атак, как объекты IDbCommand для база данных.
прямо сейчас мы используем очень примитивную подстановку строк, которая, как я подозреваю, довольно недостаточна:
protected virtual string Escape(string value) { return value .Replace(@"", @"") .Replace(@"$", @"$") .Replace(@"""", @"""") .Replace("`", "'") ; }
что вы, ребята, делаете, чтобы предотвратить атаки инъекций командной строки? Мы планируем реализовать регулярное выражение, которое очень строгое и допускает только очень небольшое подмножество символов, но мне было интересно, есть ли лучший способ.
некоторые уточнения:
- некоторые из этих инструментов не имеют APIs мы можем запрограммировать против. Если бы они это сделали, у нас не было бы этой проблемы.
- пользователи не выбирают инструменты для выполнения, они вводят метаданные, которые используют выбранные нами инструменты (например, вводят метаданные, такие как уведомления об авторских правах в целевые файлы).
7 ответов
вы выполняете программы напрямую или проходите через оболочку? Если вы всегда запускаете внешнюю программу, давая полное имя пути к исполняемому файлу и оставляя оболочку вне уравнения, то вы не очень восприимчивы к какой-либо инъекции командной строки.
EDIT: DrFloyd, оболочка отвечает за оценку таких вещей, как backtick. Нет оболочки, нет оценки оболочки. Очевидно, вы должны быть осведомлены о любых потенциальных проблем безопасности в программы, которые вы назвали, но я не думаю, что этот вопрос об этом.
в C++ on окна, вы просто escape \ and " где это необходимо, процитируйте аргумент и ShellExecute его. Затем все внутри кавычек должно рассматриваться как текст.
это иллюстрирует:
#include <iostream>
#include <string>
#include <windows.h>
#include <cstdlib>
using namespace std;
// Escape and quote string for use as Windows command line argument
string qEscape(const string& s) {
string result("\"");
for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
const char c = *i;
const string::const_iterator next = i + 1;
if (c == '"' || (c == '\' && (next == s.end() || *next == '"'))) {
result += '\';
}
result += c;
}
result += '"';
return result;
}
int main() {
// Argument value to pass: c:\program files\test\test.exe
const string safe_program = qEscape("c:\program files\test\test.exe");
cout << safe_program << " ";
// Argument value to pass: You're the "best" around.
const string safe_arg0 = qEscape("You're the \"best\" around.");
// Argument value to pass: "Nothing's" gonna ever keep you down.
const string safe_arg1 = qEscape("\"Nothing's\" gonna ever keep you down.");
const string safe_args = safe_arg0 + " " + safe_arg1;
cout << safe_args << "\n\n";
// c:\program files\test\ to pass.
const string bs_at_end_example = qEscape("c:\program files\test\");
cout << bs_at_end_example << "\n\n";
const int result = reinterpret_cast<int>(ShellExecute(NULL, "open", safe_program.c_str(), safe_args.c_str(), NULL, SW_SHOWNORMAL));
if (result < 33) {
cout << "ShellExecute failed with Error code " << result << "\n";
return EXIT_FAILURE;
}
}
но, с любым методом вы используете, вы должны испытать ад из его для того чтобы увидеть что оно действительно предотвращает впрыску.
Не используйте черный список для предотвращения инъекций. Если есть n способы введения кода, Вы будете думать о n-m здесь m > 0.
используйте белый список принятых параметров (или шаблонов). Она гораздо более ограничительна по своей природе, но такова природа безопасности.
Ну, если вы можете вызвать инструменты программно без командной строки, это, вероятно, будет вашим лучшим вариантом. В противном случае вы можете потенциально выполнить инструмент командной строки через пользователя, у которого нет абсолютно никакого доступа к чему-либо (за исключением, возможно, одного каталога, с которым они не могут причинить никакого вреда)... хотя это может привести к нарушению инструмента, в зависимости от того, что делает инструмент.
просто обратите внимание, мне никогда не приходилось сталкиваться с этой проблемой, потому что мне никогда не приходилось вызова инструмента командной строки из внешнего приложения, где инструмент требует ввода от пользователя.
Хммм...
похоже, у вас есть список допустимых команд, которые пользователи могут выполнять. Но вы же не хотите, чтобы их всех казнили.
вы можете попытаться взять фактическую командную строку и проверить, что файл существует в "безопасном" месте, по крайней мере.
вы также можете решить проблему с большим интерфейсом, предоставить выпадающий список команд и параметров, которые они могут использовать. Это больше работы с вашей стороны, но в конечном итоге это помогает пользователям.
вы выполняете программы напрямую или проходите через оболочку? Если вы всегда запускаете внешнюю программу, давая полное имя пути к исполняемому файлу и оставляя оболочку вне уравнения, то вы не очень восприимчивы к какой-либо инъекции командной строки.
@Curt Hagenlocher backtick может убить вас. Если система Windows настроена "неправильно" или система unix позволяет это, dir &bt; del * & bt; сначала выполнит del * команда затем использует вывод вместо del *, который в этом случае не будет иметь значения, потому что нет ничего для dir (или ls)