Изменение аргументов командной строки, чтобы они не были видны в выводе ps - PullRequest
3 голосов
/ 28 сентября 2010

У меня есть исполняемый файл, который принимает определенные аргументы командной строки. Любой пользователь на машине может найти аргументы, выполнив ps (Unix) или procxp (Windows). Некоторые из этих аргументов такие вещи, как пароли. Я знаю, что мы не должны передавать такие пароли.

Есть ли какой-нибудь способ в коде исполняемого файла, который я могу изменить, чтобы другие пользователи, выполняющие ps / procxp, не могли видеть аргументы командной строки, используемые для запуска исполняемого файла?

Я уверен, что не существует независимого от платформы способа сделать это, но даже если для каждой платформы есть какой-либо специфический для каждой платформы API, это будет хорошей отправной точкой. Я с нетерпением жду каких-либо комментариев / предложений или мыслей.

С уважением,

Ash

Ответы [ 8 ]

6 голосов
/ 28 сентября 2010

Вы пытаетесь сделать небезопасное решение немного более безопасным. Почему бы просто не сделать его более безопасным?

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

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

3 голосов
/ 28 сентября 2010

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

Если вам нужна эта функция (передача паролей в командной строке, что очень и очень плохо идея), вам следует использовать усиленное ядро, которое позволяет полностью отключить чтение аргументов командной строки или даже полностью отключить функциональность ps.Один дешевый способ сделать это (но это может сломать вещи) - просто отключить /proc.

2 голосов
/ 29 сентября 2010

Я думаю, что основной ответ, вероятно, состоит в том, чтобы не передавать данные в командной строке, а вместо этого использовать RPC. stdin - это RPC для плохого человека, так как он записывает в файл, который вы затем удаляете, и есть более сложные методы.

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

Любое решение RPC требует модификации обеих сторон связи, однако, очевидно. Однако попытка запутать данные, изменив ОС для предотвращения нормальных операций или полагаясь на недокументированное поведение во время выполнения, кажется плохой идеей с точки зрения безопасности.

Надеюсь, это поможет.

2 голосов
/ 29 сентября 2010

Этот init пример дает мне ошибку сегментации

Этот, однако, работает:

int main(int argc, char *argv[])
{
    char * argv0 = argv[0];
    int i;
    size_t len;
    for (i = 0; i <argc; ++i)
    {
        len = strlen(argv[i]);
        memset(argv[i], 0, len);
    }
    strcpy(argv0, "Hey, can you see me?");
    for (;;);
    return 0;
}
2 голосов
/ 28 сентября 2010

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

1 голос
/ 28 сентября 2010

Некоторые версии init перезаписывают свою командную строку, поэтому они отображаются как init в списке ps.

int main(int argc, char * argv[]) {
   // process the arguments or make a copy of them
   // and then

   char * argv0 = argv[0];
   while (*argv++) {
      size_t len = strlen(*argv);
      memset(*argv, 0, len);
   }
   strcpy(argv0, "init");

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

Это все еще неработающий способ передачи конфиденциальной информации через командную строку (или переменные окружения, поскольку они доступны в /proc/<pid>/environ так же, как argv в /proc/<pid>/cmdline под Linux).

0 голосов
/ 29 сентября 2010

Я обычно читаю все конфиденциальные данные со стандартного ввода.Например, в isql (оболочка Sybase SQL) в Linux я делаю что-то вроде

isql -U username <<EOD
password
select * from whatever
go
0 голосов
/ 28 сентября 2010

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

Единственный хороший ответ - не позволяйте им передавать информацию в командной строке.

...