Как разрешить пользователям выполнять скрипт, не раскрывая защищенную информацию

326
WTK

Учитывая, что у пользователя root есть некоторые учетные данные (скажем, ключ API), заданные в переменной среды, и при наличии непривилегированного пользователя John, как я могу позволить Джону выполнить сценарий, который использует указанный ключ API, без риска утечки его значения Джону ?

1
Мне кажется, что вам понадобится какая-нибудь прокси-программа, работающая под пользователем root, которая выполняет работу * для * Джона и передает обратно информацию, которую Джон хочет. Mokubai 6 лет назад 4
Хм, @Mokubai еще какие-нибудь указатели или примеры, на которые я могу положиться? И еще одно замечание - я читал, что с помощью некоторого mumbo-jumbo я могу сделать сценарий исполняемым, но не читаемым, будет ли это работать в этом случае? WTK 6 лет назад 0
Я действительно не вижу способа сделать скрипт исполняемым, но каким-то образом не читаемым. Вы можете запустить скрипт как другой пользователь, но тогда вам нужно либо дать пользователю пароль, либо разрешение `sudo` для его запуска, которое, как мне кажется, трудно поверить, может быть сделано полностью безопасным для предотвращения простого чтения. Если у вас есть доказательства обратного, было бы хорошо показать. У меня нет примеров того, как это должно быть сделано, есть слишком много способов, и мы не знаем, какие у вас есть ограничения, кроме утечки этого ключа. Mokubai 6 лет назад 0

1 ответ на вопрос

2
G-Man

Вопрос кажется немного не сфокусированным.

  • Вопрос сам по себе говорит о получении значения из «переменной среды суперпользователя» (т. Е. «Корневой переменной среды»). Я даже не уверен, что это значит. Вы говорите, что Джон должен получить значение из среды (другого) пользователя, вошедшего в систему как «root», или который работает как «root» через suили sudo? Или вы говорите о среде процесса (возможно, фонового), выполняющегося от имени пользователя root?

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

  • Но затем в комментарии вы говорите о создании сценария исполняемого, но не читаемого. Это говорит о том, что вы готовы иметь ключ, жестко запрограммированный в сценарии, если пользователи без прав root не могут его прочитать. Это говорит о том, что ключ очень статичен и меняется настолько редко, что вы готовы изменять скрипт каждый раз, когда ключ меняется.

    U & L имеет длинную тему на эту тему: может ли скрипт быть исполняемым, но не читаемым?   К сожалению, большинство ответов отрицательные или являются отклонениями, отклонениями или обходными путями, некоторые из которых работают лучше, чем другие. Например, Сантана предлагает создать запись, /etc/sudoers которая позволяет Джону бежать сценарий с повышенными правами доступа, не имея возможности читать его как самого себя. Но если сценарию не нужны повышенные разрешения (кроме получения ключа), вы не хотите запускать его с повышенными разрешениями.

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

  • ИМХО, наиболее разумная / правдоподобная интерпретация заключается в том, что ключ хранится в файле, который Джон не может прочитать. Традиционным способом реализации таких соглашений является setUID и / или setGID. ( sudoтакже полезно.)

Вот пример того, как это сделать. Напишите программу на C, например:

#include <stdio.h> #include <stdlib.h>  #define KEY_FILE (соответствующий путь) #define SCRIPT (соответствующий путь)  главный() { FILE * key_fp; символ ключа [80]; (отрегулируйте соответственно) gid_t gid; uid_t uid; char * args [10]; (отрегулируйте соответственно)  key_fp = fopen (KEY_FILE, "r"); if (key_fp == NULL) { PError (KEY_FILE); выход (1); } (ваш код для чтения и проверки ключа ) fclose (key_fp); if (setenv ("KEY", key, 1)! = 0) { fprintf (stderr, "Проблема с setenv (). \ n"); выход (1); } gid = getgid (); uid = getuid (); // использовать // if (setresgid (gid, gid, gid)! = 0 || setresuid (uid, uid, uid)! = 0) // если они доступны; иначе if (setregid (gid, gid)! = 0 || setreuid (uid, uid)! = 0) { fprintf (stderr, "Проблемы с удалением привилегий. \ n"); выход (1); } args [0] = "scriptname"; (отрегулируйте соответственно) args [1] = NULL; execv (сценарий, аргументы); PError (SCRIPT); выход (1); }

Определите KEY_FILEполный путь к файлу, который содержит ключ, и укажите SCRIPTполный путь к файлу, который содержит сценарий. Убедитесь, что у Джона есть доступ на чтение к сценарию, но не к файлу ключа, и что у него нет прав на запись ни в один из каталогов в любом из путей. Сделайте так, чтобы эта программа могла читать файл ключа, задав для него setUID и / или setGID. Он прочитает ключ, вставит его в среду, сбросит привилегии и выполнит скрипт. (Вы можете захотеть изменить приведенный выше код, чтобы аргументы командной строки, передаваемые программе, передавались в сценарий.)

Как указано выше, сценарий будет выполняться с UID и GID Джона, но с ключом в среде. В некоторых системах Джон может читать среду сценария из или с помощью . Если это так, может быть полезно, чтобы скрипт немедленно скопировал ключ в локальную (не экспортируемую) переменную и сбросил ее ./proc/(pid_of_script)/environpsKEY

Вероятно, для сценария будет безопасно передать ключ программе

  • через трубу (например, ),printf "%s" (key_value) | (program)
  • через здесь документ, или
  • через строку здесь.

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

Если вы хотите, чтобы программа работала sudo, вам может понадобиться жестко кодировать UID и GID Джона, потому что он sudoустанавливает реальные и эффективные идентификаторы.