Учитывая, что у пользователя root есть некоторые учетные данные (скажем, ключ API), заданные в переменной среды, и при наличии непривилегированного пользователя John, как я могу позволить Джону выполнить сценарий, который использует указанный ключ API, без риска утечки его значения Джону ?
1 ответ
Вопрос кажется немного не сфокусированным.
Вопрос сам по себе говорит о получении значения из «переменной среды суперпользователя» (т. Е. «Корневой переменной среды»). Я даже не уверен, что это значит. Вы говорите, что Джон должен получить значение из среды (другого) пользователя, вошедшего в систему как «root», или который работает как «root» через
suилиsudo? Или вы говорите о среде процесса (возможно, фонового), выполняющегося от имени пользователя root?Но, какие бы детали вы ни имели в виду, звучит так, будто ключ очень динамичный и эфемерный. Поскольку я не понимаю, что это значит, я не скажу, что это невозможно, но звучит сложно.
Но затем в комментарии вы говорите о создании сценария исполняемого, но не читаемого. Это говорит о том, что вы готовы иметь ключ, жестко запрограммированный в сценарии, если пользователи без прав root не могут его прочитать. Это говорит о том, что ключ очень статичен и меняется настолько редко, что вы готовы изменять скрипт каждый раз, когда ключ меняется.
U & L имеет длинную тему на эту тему:может ли скрипт быть исполняемым, но не читаемым? К сожалению, большинство ответов отрицательные или являются отклонениями, отклонениями или обходными путями, некоторые из которых работают лучше, чем другие. Например, Сантана предлагает создать запись в
/etc/sudoersкоторая позволит Джону запускать сценарий с повышенными разрешениями, но при этом не сможет читать его самому. Но если сценарию не нужны повышенные разрешения (кроме получения ключа), вы не хотите запускать его с повышенными разрешениями.Однако в этом связанном вопросе (о суперпользователе ) я представляю хитрый способ сделать скрипт исполняемым, но не читаемым, обернув его в программу на Си. Как я объясняю в этом ответе, эта техника не является надежной; Есть способы, которыми информация может просочиться.
ИМХО, наиболее разумная / правдоподобная интерпретация заключается в том, что ключ хранится в файле, который Джон не может прочитать. Традиционным способом реализации таких соглашений является setUID и / или setGID. (
sudoтакже полезно.)
Вот пример того, как это сделать. Напишите программу на C, например:
#include <stdio.h>
#include <stdlib.h>
#define KEY_FILE (appropriate pathname)
#define SCRIPT (appropriate pathname)
main()
{
FILE *key_fp;
char key[80]; (adjust as appropriate)
gid_t gid;
uid_t uid;
char *args[10]; (adjust as appropriate)
key_fp = fopen(KEY_FILE, "r");
if (key_fp == NULL)
{
perror(KEY_FILE);
exit(1);
}
(your code to read and validate key)
fclose(key_fp);
if (setenv("KEY", key, 1) != 0)
{
fprintf(stderr, "Problem with setenv().\n");
exit(1);
}
gid = getgid();
uid = getuid();
// use
// if (setresgid(gid, gid, gid) != 0 || setresuid(uid, uid, uid) != 0)
// if they’re available; otherwise
if (setregid(gid, gid) != 0 || setreuid(uid, uid) != 0)
{
fprintf(stderr, "Problem dropping privileges.\n");
exit(1);
}
args[0] = "scriptname"; (adjust as appropriate)
args[1] = NULL;
execv(SCRIPT, args);
perror(SCRIPT);
exit(1);
}
Определите KEY_FILE для полного пути к файлу, который содержит ключ, и задайте SCRIPT для полного пути к файлу, который содержит скрипт.
Убедитесь, что у Джона есть доступ на чтение к сценарию, но не к файлу ключа, и что у него нет прав на запись ни в один из каталогов в любом из путей.
Сделайте так, чтобы эта программа могла читать файл ключа, задав для него setUID и / или setGID. Он прочитает ключ, вставит его в среду, сбросит привилегии и выполнит скрипт.
(Вы можете захотеть изменить приведенный выше код, чтобы аргументы командной строки, передаваемые программе, передавались в сценарий.)
Как указано выше, сценарий будет выполняться с UID и GID Джона, но с ключом в среде.
В некоторых системах Джон может читать среду сценария из /proc/(pid_of_script)/environ или с помощью ps .
Если это так, может быть полезно, чтобы скрипт немедленно скопировал ключ в локальную (не экспортируемую) переменную и сбросил переменную KEY .
Вероятно, для сценария будет безопасно передать ключ программе
- через канал (например,
printf "%s" (key_value) | (program)), - через здесь документ, или
- через строку здесь.
Риски передачи ценности через окружающую среду упомянуты выше.
Избегайте передачи его в качестве параметра командной строки, так как это определенно может быть видно по ps .
Если вы хотите, чтобы программа работала через sudo , вам может понадобиться жестко кодировать UID и GID Джона, потому что sudo устанавливает как действительные, так и действительные идентификаторы.
