Изменение аргументов командной строки, чтобы их нельзя было увидеть в выводе ps

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

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

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

С уважением,

Пепел


person ash    schedule 28.09.2010    source источник
comment
Надеюсь, вы сделали символическую ссылку на ~/.bash_history на /dev/null...   -  person meagar    schedule 28.09.2010
comment
Потребовалось время, чтобы найти его, но stackoverflow.com/questions/3760896/ предполагает, что на некоторых платформах вы можете просто изменить содержимое строк, на которые указывает argc[]   -  person torak    schedule 28.09.2010
comment
Не то, чтобы я рекомендовал это, но в Windows вы можете перезаписать буфер, который вы возвращаете из GetCommandLine().   -  person Luke    schedule 28.09.2010


Ответы (8)


Этот 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;
}
person ecik    schedule 28.09.2010

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

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

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

person RyanHennig    schedule 28.09.2010

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

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

person R.. GitHub STOP HELPING ICE    schedule 28.09.2010

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

person Community    schedule 28.09.2010

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

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

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

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

person Nick    schedule 29.09.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).

person nategoose    schedule 28.09.2010
comment
Окружающая среда кажется мне более безопасной: cat: /proc/1/environ: Permission denied. - person SamB; 12.02.2012

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

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

person Greg Domjan    schedule 28.09.2010

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

isql -U username <<EOD
password
select * from whatever
go
person Community    schedule 28.09.2010