#python #c #linux #file-permissions
#python #c #linux #файл-разрешения
Вопрос:
Этот вопрос заключается в том, как создать скрипт на Python, который другие (не root) пользователи могут запускать, но не проверять.
Пример использования:
#!/usr/bin/env python
import requests
params = { 'user':'fred', 'password':'123' }
url = 'https://.......'
print(requests.get(url, params).content)
В этом примере (но это всего лишь пример) я хочу разрешить пользователям запускать скрипт, чтобы получить веб-контент, который был извлечен, но не видеть учетные данные, которые использовались для извлечения этого контента.
Установка разрешения на выполнение, но не разрешения на чтение, не дает того же результата, что и для скомпилированного исполняемого файла. Вот пример «привет, мир».
В C:
$ cat test.c
#include <stdio.h>
int main() {
puts("secret message");
return 0;
}
$ gcc -o secret test.c
$ chmod 711 secret
$ sudo -u nobody ./secret
secret message
$ sudo -u nobody strings ./secret
strings: ./secret: Permission denied
В Python:
$ cat test.py
#!/usr/bin/python
print("secret message")
$ chmod 711 test.py
$ sudo -u nobody ./test.py
/usr/bin/python: can't open file './test.py': [Errno 13] Permission denied
(Конечно, python
сам исполняемый файл может быть настроен на восьмеричный режим 711, но это не то, что я хочу защитить.)
Итак, что я могу с этим поделать?
Возможные решения, о которых я думал, но я думаю, что это не сработает:
(1) Переведите всю программу Python на C.
Возможно в принципе, но не является практическим решением. Даже для этого простого примера это означало бы необходимость поиска эквивалента requests
библиотеки.
(2) Есть вспомогательная программа на C, которая вызывается Python.
Что на самом деле должна делать вспомогательная программа C? Если он просто печатает пароль, то пользователь может запустить его напрямую, чтобы получить пароль. Если он также извлекает веб-страницу (в этом примере), то мы возвращаемся к проблеме 1.
(3) Есть программа на C, которая запускает python и передает секретные данные в python:
-
(a) через командную строку
- открыть для проверки через
ps
или/proc/<pid>/cmdline
- открыть для проверки через
-
(б) через среду
- открыть для проверки через
ps
или/proc/<pid>/environ
- открыть для проверки через
-
(c) через стандартный ввод
- предотвращает использование стандартного ввода для других целей в скрипте Python, например, пользовательского ввода
-
(d) через именованный канал
- пользователь может запустить процесс Python для чтения из именованного канала (если они сначала выполняют
killall -STOP python
в замкнутом цикле, то с приостановленным процессом python тривиально выиграть гонку для чтения из именованного канала)
- пользователь может запустить процесс Python для чтения из именованного канала (если они сначала выполняют
На самом деле я подумал еще об одной вещи — адаптация 3c — программа на C разветвляет и запускает процесс python и отправляет ему (через stdin) секрет, за которым следуют данные из его собственного stdin. Процесс python начинается с чтения секрета, а затем может свободно считывать другой пользовательский ввод из stdin. Но все это начинает казаться неуклюжим (теперь у нас есть этот дополнительный процесс, копирующий данные из stdin на время процесса python), и в любом случае я понятия не имею, как написать такую программу на C.
Что я могу сделать, пожалуйста?
Комментарии:
1. выполнение afaik позволяет подключить отладчик. Отладчик может просматривать память, в которую загружена ваша программа, там вы найдете свой секрет во всей красе.
2. Если это ваш способ «защиты» жестко закодированных учетных данных в вашем скрипте / приложении, то в вашем дизайне есть что-то фундаментально небезопасное.
3. Принципиально не работает: кто-то может просто запустить вашу программу в отладчике.
Ответ №1:
Можете ли вы не использовать свой код Python в качестве интерпретируемого скрипта, а скомпилировать его в исполняемый файл командной строки? Это похоже на ваше первое предложенное решение, но в этом случае не было бы необходимости компилировать файл .py в файл .c, а затем файл .c в исполняемый файл. Вы скомпилируете файл .py непосредственно в исполняемый файл.
Комментарии:
1. И пользователь по-прежнему сможет видеть учетные данные, используемые с помощью простых инструментов, таких как
strace
илиstrings
.
Ответ №2:
Вы можете встроить все приложение Python в качестве исходного кода в двоичный файл C, используя методы, подобные описанному здесь:
https://www.codeproject.com/articles/820116/embedding-python-program-in-a-c-cplusplus-code
Насколько это практично, зависит от сложности приложения на Python. Некоторые компоновщики (например, gcc) позволят вам встроить полный файл в двоичный файл таким образом, чтобы он загружался в память по указанному адресу. Затем вы можете передать этот адрес в среду выполнения Python. Это менее некрасиво, чем превращать весь ваш код Python в строки C или base64. Однако не все компоновщики допускают такой трюк.
Эти методы позволят вам сделать двоичный файл нечитаемым, но они не помешают кому-либо подключить отладчик к запущенному двоичному файлу и покопаться в памяти. Но это верно и для родного приложения на языке Си. Если вам нужна защита от такого рода угроз — на любом языке — вам нужно будет выполнить надлежащую криптографию ваших секретных данных и убедиться, что вы записываете все содержимое памяти после вызова API и т.д. Это серьезный, нетривиальный материал, и вы должны сопоставить риск безопасности с объемом работы, связанной с управлением им.