Подтвердить что ты не робот

Скрытие секретности из параметра командной строки в Unix

У меня есть script, который запускает внутри себя команду с параметром, который является секретом. Например:

#!/bin/bash
command-name secret

Во время выполнения команды я могу прочитать ps -ef | grep command-name, который является секретом.

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

4b9b3361

Ответ 1

Если секрет не изменяется между исполнениями, используйте специальный файл конфигурации ".appsecrets". Установите разрешения для файла только для чтения владельцем. Внутри файла задается переменная окружения. Файл должен находиться в домашнем каталоге пользователя, выполняющего команду.

#!/bin/bash  
#filename: .appsecrets
set SECRET=polkalover  

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

. ~/.appsecrets

Что я видел:

1)
 echo $SECRET | command

работает, если команда запрашивает пароль из stdin AND, если "echo" является встроенным в вашу оболочку. Мы использовали Korn.

2)
 password=$ENV{"SECRET"};

работает, если у вас есть контроль над кодом (например, в perl или С++)

3)
  . ./.app.config #sets the environment variables
isql -host [host] -user [user] -password <<SECRET
${SQLPASSWORD}
SECRET

работает, если команда может принять секрет из std-in. Одно из ограничений заключается в том, что строка << должна быть последним аргументом команды. Это может быть неприятно, если есть необязательный аргумент arg, который должен появиться после -password

Преимущество такого подхода заключается в том, что вы можете организовать его, чтобы секрет мог быть скрыт в производстве. Используйте одно и то же имя файла в процессе производства, но оно будет находиться в домашнем каталоге учетной записи, которая запускает команду в процессе производства. Затем вы можете заблокировать доступ к тайне, как если бы вы получили доступ к учетной записи root. Только определенные люди могут "su" для учетной записи prod просматривать или поддерживать секрет, в то время как разработчики все еще могут запускать программу, потому что они используют свой собственный файл .appsecret в своем домашнем каталоге.

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

(НЕПРАВИЛЬНЫЙ ПУТЬ)
Один старый метод, который я видел, использовал DBA, чтобы установить SYBASE в "/opt/././././././././././././././././././././././././././././././././././sybase/bin". Таким образом, их командные строки были настолько длинными, что ps урезал его. Но в Linux я думаю, что вы могли бы вынюхивать полную командную строку из/proc.

Ответ 2

  1. Во-первых, вы не можете скрыть аргументы командной строки. Они по-прежнему будут видны через ps aux и cat/proc/$YOUR_PROCESS_PID/cmdline во время запуска программы (до того, как программа сможет внести изменения в аргументы во время выполнения). Хорошей новостью является то, что вы все еще можете иметь секрет, используя альтернативы:

  2. Используйте переменные среды. Если ваша программа может их прочитать, сделайте это:

    mySecret='hello-neo' myCommand
    
  3. Используйте стандартный ввод:

    mySecret='hello-neo' printenv mySecret | myCommand
    
  4. Используйте временный дескриптор файла:

    myCommand <( mySecret='hello-neo' printenv mySecret )
    

В последнем случае ваша программа будет запущена как myCommand/dev/fd/67, где содержимое /dev/fd/67 является вашим секретом (в этом примере hello-neo).


Во всех вышеперечисленных подходах с осторожностью оставляйте команду в истории команд bash (~/.bash_history). Вы можете избежать этого, либо запустив команду из скрипта (файла), либо каждый раз запрашивая пароль в интерактивном режиме:

    read mySecret
    myCommand  # approach 2
    printenv mySecret | myCommand  # approach 3
    myCommand <( printenv mySecret )  # approach 4

Ответ 3

Единственный способ скрыть свой секретный аргумент из ps - это не предоставление тайны в качестве аргумента. Один из способов сделать это - поместить секрет в файл и перенаправить файловый дескриптор 3, чтобы прочитать файл, а затем удалить файл:

echo secret > x.$$
command 3<x.$$
rm -f x.$$

Не совсем ясно, что это безопасный способ спасти секрет; команда echo является встроенной оболочкой, поэтому она не должна появляться в выводе "ps" (и любое появление было бы мимолетным). Когда-то очень давно, echo не был встроен - действительно, на MacOS X все еще есть /bin/echo, хотя он является встроенным для всех оболочек.

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

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

Закрепление аргумента изнутри программы - например, перезапись нулями - не скрывает аргумент от "ps".

Ответ 4

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

Ответ 5

Я видел это в другом посте. Это самый простой способ под Linux.

Это изменяет часть памяти командной строки, которую видят все другие программы.

strncpy(argv[1], "randomtrash", strlen(argv[1]));

Вы также можете изменить имя процесса, но только при чтении из командной строки. Программы типа top покажут реальное имя процесса:

strncpy(argv[0], "New process name", strlen(argv[0]));

Не забудьте скопировать максимум байтов strlen(argv[0]) потому что, вероятно, больше не выделено места.

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

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

Ответ 6

Там нет простого способа. Взгляните на этот вопрос, который я задал давно:

Скрыть аргументы из ps

Является ли command вашей собственной программой? Вы можете попробовать шифровать секрет и command дешифровать его перед использованием.

Ответ 8

Если script предназначен для запуска вручную, лучший способ - прочитать его с помощью STDIN

#!/bin/bash
read -s -p "Enter your secret: " secret

command "$secret"

Ответ 9

Возможно, вы можете сделать следующее:

#include <boost/algorithm/string/predicate.hpp>
void hide(int argc, char** argv, std::string const & arg){
    for(char** current = argv; current != argv+ argc ;++current){
        if(boost::algorithm::starts_with(*current, "--"+arg)){
            bzero(*current, strlen(*current));
        }
    }
}
int main(int argc, char** argv){
   hide(argc,  argv, "password");
}

Ответ 10

Вы можете использовать LD_PRELOAD чтобы библиотека манипулировала аргументами командной строки некоторого двоичного файла в процессе самого этого двоичного файла, где ps не берет его. Смотрите этот мой ответ на Server Fault для деталей.

Ответ 11

Вот один из способов скрыть секрет в переменной окружения от ps:

#!/bin/bash
read -s -p "Enter your secret: " secret

umask 077 # nobody but the user can read the file x.$$ 
echo "export ES_PASSWORD=$secret" > x.$$
. x.$$ && your_awesome_command
rm -f x.$$ # Use shred, wipe or srm to securely delete the file


В выводе ps вы увидите что-то вроде этого:

$ps -ef | grep udcs
root     23134     1  0 20:55 pts/1    00:00:00  . x.$$ && your_awesome_command

Elastalert и Logstash являются примерами сервисов, которые могут получить доступ к паролям через переменные среды.