2008-09-04 2 views
9

В настоящее время мы создаем приложение, которое выполняет ряд внешних инструментов. Нам часто приходится передавать информацию, введенную пользователями в наши системы.Предотвращение инъекций в командной строке

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

К сожалению, мы еще не нашли классов в .NET Framework, которые выполняют программы с командной строкой, предоставляя тем же типам защиты от инъекционных атак, что и объекты IDbCommand для баз данных.

Сейчас мы используем очень примитивную строку замещения, которую я подозреваю, весьма недостаточным:

protected virtual string Escape(string value) 
{ 
     return value 
     .Replace(@"\", @"\\") 
     .Replace(@"$", @"\$") 
     .Replace(@"""", @"\""") 
     .Replace("`", "'") 
     ; 
} 

Что вы, ребята, чтобы предотвратить атаки инъекционные командной строки? Мы планируем внедрить регулярное выражение, которое является очень строгим и допускает только очень небольшое подмножество символов, но мне было интересно, есть ли лучший способ.

Некоторые пояснения:

  • Некоторые из этих инструментов не имеют API, мы можем программировать против. Если бы они это сделали, у нас не было бы этой проблемы.
  • Пользователи не выбирают инструменты для выполнения, они вводят метаданные, которые использовались нами для использования (например, ввод метаданных, таких как уведомления об авторских правах, в целевые файлы).

ответ

5

Выполнение программ непосредственно или через оболочку? Если вы всегда запускаете внешнюю программу, предоставляя полное имя пути исполняемому файлу и оставляя оболочку из уравнения, тогда вы действительно не подвержены любой инъекции командной строки.

EDIT: DrFloyd, оболочка отвечает за оценку таких вещей, как обратная сторона. Нет оболочки, нет оценки оболочки. Очевидно, что вы все еще должны знать о любых потенциальных проблемах безопасности в программах, которые вы вызываете, но я не думаю, что этот вопрос об этом.

0

Ну, если вы можете программно использовать инструменты без командной строки, это, вероятно, будет вашим лучшим вариантом. В противном случае вы можете запустить инструмент командной строки с помощью пользователя, который абсолютно не имеет доступа к чему-либо (кроме, возможно, единственного каталога, с которым они не могут нанести вреда) ... хотя это может привести к разрыву инструмента, в зависимости от на том, что делает инструмент.

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

0

Хммм ...

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

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

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

0

Выполнение программ непосредственно или через оболочку? Если вы всегда запускаете внешнюю программу, предоставляя полное имя пути исполняемому файлу и оставляя оболочку из уравнения, тогда вы действительно не подвержены любой инъекции командной строки.

@Curt Hagenlocher Открывающая кавычка может убить вас. Если система Windows настроена «неправильно», или система unix разрешает ее, dir &bt; del * &bt; сначала выполнит команду del *, а затем использует результат вместо del *, который в этом случае не имеет значения потому что нет ничего для dir (или ls)

2

Когда вы Process.Start новый процесс, поставьте параметры в его аргументе Parameters, а не стройте всю командную строку самостоятельно.

Не успел пройти надлежащий тест, но я думаю, что это должно помочь защитить его до определенного уровня.

Проверит это завтра.

EDIT: А, кто-то избил меня еще раз. Но вот еще один момент: попробуйте использовать Console.InputStream (не помните точное имя) для передачи данных вместо передачи параметров, является ли это возможным решением? например, исправить команду, чтобы она читала с устройства CON, и затем вы отправляете данные через входной поток.

2

В C++ на Windows,, вы просто бежать \ и ", где это необходимо, цитирую аргумент и 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; 
    } 
} 

Но при любом методе вы используете, вы должны проверить ад из нее, чтобы увидеть, что это действительно предотвратить инъекции.

1

не использовать черный список для предотвращения инъекций. Если есть n способов введения кода, вы будете думать о n - m где m> 0.

Использовать белый список принятых параметров (или шаблонов). Он носит гораздо более ограничительный характер, но это характер безопасности.

Смежные вопросы