sudo
다른 사용자로 프로세스를 실행하는 데 사용해야 합니다 . 그러나 sudo
다음과 같은 것을 사용하는 방법은 다음과 같습니다 exec
.
sudo -u www-data exec php -r 'sleep(2); echo 5;'
sudo 프로세스를 바꾸시겠습니까?
이유와 요구 사항은 무엇입니까?
- 총 프로세스 수 최소화
- 명령은 계속해서 시작되므로 한 번에 모두 시작할 수는 없습니다.
sudo
- 솔루션은 아무 것도 없는 것처럼
exec
, 즉 배경이 없는 것처럼 동작해야 합니다.
답변1
sudo(8) 매뉴얼 페이지에서:
특별한 경우로, 정책 플러그인이 닫기 기능을 정의하지 않고 pty가 필요하지 않은 경우 sudo는 먼저 fork(2)를 호출하지 않고 명령을 직접 실행합니다. sudoers 정책 플러그인은 I/O 로깅이 활성화되거나, pty가 필요하거나, pam_session 또는 pam_setcred 옵션이 활성화된 경우에만 종료 기능을 정의합니다.
일반적인 상황에서 이는 프로세스가 TTY에서 연결 해제되었는지 확인하면 포크되지 않음을 의미합니다. 예를 들어:
sudo -u www-data php -r 'sleep(2); echo 5;' < /dev/null > /dev/null 2>&1
추가 절차는 생략됩니다. 특정 출력이 필요한 경우 TTY가 아닌 파일이나 이와 유사한 파일로 전달하고 나머지는 /dev/null
위에 표시된 대로 그대로 두십시오.
프로세스 목록에서 원래 sudo 명령을 보는 부작용이 여전히 있다는 것을 알았지만 아마도 괜찮을 것입니다. 또는 이러한 요구 사항을 보완하기 위해 프로세스 목록에 프로세스가 표시되는 방식을 변경하는 일부 PHP 함수 또는 유사한 호출이 있을 수 있습니다.
고쳐 쓰다:
많은 시스템에서는 기본적으로 pam 옵션이 활성화되어 있는 것으로 보입니다. 비활성화할 수 있지만 "명령을 실행해도 리소스 제한이 업데이트되지 않을 수 있습니다"와 같은 부작용이 있다는 점에 유의하세요. 자세한 내용은 sudoers(5)를 참조하세요. 전역적으로 비활성화하려면 다음 줄을 추가하면 됩니다 /etc/sudoers
.
Defaults !pam_setcred
Defaults !pam_session
특정 사용자 또는 이와 유사한 사용자로 설정을 제한하는 방법을 보려면 sudoers(5) 매뉴얼 페이지를 확인하십시오. 매뉴얼 페이지에서 "Default_Type"을 찾으십시오.
답변2
편집: 내 원래 답변은 다음과 같습니다(SO가 취소선을 지원하지 않기 때문에 인용됨).
원래:
정답은 단순히 할 수 없다는 것입니다. 적어도 안정적이고 쉽지는 않습니다.
수정됨: 정답은 '예'입니다. 아주 조심스럽게요. 하단의 부록을 참조하세요.
fork()
다른 의견 작성자가 인용한 섹션의 매뉴얼 페이지 내용에도 불구하고 이는 대부분의 경우(99.9%) 시스템의 기본 sudo 프로세스 모델입니다.
htop
와 같은 프로세스 모니터를 사용하면 직접 진실을 쉽게 확인할 수 있습니다 ps --forest
.
제안된 답변:
<?php
exec("exec sudo -u www-data php -r 'sleep(2); echo 5;' < /dev/null > /dev/null 2>&1");
느린 sudo 프로세스가 남습니다.
php spawn-test.php
└─ sudo -u www-data php -r 'sleep(2); echo 5;'
└─ php -r 'sleep(2); echo 5;'
PHP가 sudo를 호출하는 한 드라이버 스크립트는 어떻게든 일부 제어 터미널에 바인딩됩니다(편집: 또는 하위 프로세스를 pty에 작성).
그 이유는 "현대적인" sudo
환경 때문일 수 있습니다. 세션에서 원하는 모든 작업을 수행할 수 있는 sudo
티켓팅 및 플러그인에 tty 식별을 사용하세요 . pam
어떤 경우에는 대부분의 소프트웨어가 일반적으로 단순히 pam을 컴파일하여 execve()
경로를 비활성화합니다. 그러면 systemd-logind와 같은 대화형 "현대" 기능이 있습니다.
sudo
매우 복잡한 소프트웨어이므로 원하는 작업을 수행하기가 쉽지 않습니다.
원래:
그리고 귀하의 경우 이것은 기본적으로 불가능합니다.
편집: 상황에 따라 여전히 가능할 수도 있습니다.
그러나 여러 sudo
인스턴스가 하위 항목을 기다리도록 하는 것은 일반적으로 문제가 되지 않습니다. *nix 시스템에서 프로세스는 수백만 개의 .so 라이브러리에 동적으로 연결되어 있는 오늘날에도 매우 저렴한 엔터티입니다.
안심하고 sudo
지체하셔도 됩니다"적절하게"즉, 최소한의 컴퓨팅 리소스(거의 0)를 소비하며 운영 체제는 실행 중인 모든 인스턴스 간에 가능한 한 많은 메모리를 공유할 수 있을 만큼 똑똑하다는 의미입니다 sudo
. 그러니 전혀 문제로 여겨서는 안 됩니다.
이제 문제는 왜 sudo
중간 프로세스를 제거하는가입니다.
이유가 적절한 이유 없이 sudo 프로세스를 "좋아하지" 않기 때문이라면 이는 잘못된 이유입니다.
물론 SUID를 통해 루팅하고 권한을 제거하면 확실히 수행할 수 있지만 이 방법은 초보자에게 친숙하지 않고 올바르게 수행하기 어렵기 때문에 매우 위험합니다.
전문가들조차 일반적으로 반대할 정도로 너무 많기 때문에 여기서는 이를 달성하는 방법에 대해 논의하지 않겠습니다.
그러나 충분히 지속된다면 여기 stackoverflow 네트워크에서도 root
SUID를 통해 다시 전환하는 방법에 대한 답이 있습니다.
이 프로세스의 상태에서는 어떤 것도 신뢰할 수 없으며(환경 변수도 포함) 대상 사용자에게 가능한 한 빨리(그리고 올바르게 수행) 권한을 부여해야 합니다.
또한 배포 플랫폼에 따라 selinux 또는 기타 보안 프레임워크와 같은 것을 고려할 수도 있습니다.
마지막으로, 자녀의 사용자가 상위 프로세스를 구동하는 사용자와 다르면 더 많은 과정을 거치지 않고는 상태를 변경하라는 신호를 보낼 수 없습니다.
매우 어렵고 오류가 발생하기 쉬우므로 이것이 존재하는 유일한 이유입니다 . 하지만 모든 사용 사례에 항상 적합한 것은 아니라는 sudo
점에 동의합니다 .sudo
편집하다:
pam 통합, pty 생성 및 로그 서버와 같은 모든 고급 기능을 비활성화하는 방법에 대한 user11658273의 답변을 참조하십시오. 이 모든 기능이 작동하려면 비활성화되어야 하는 것 같습니다. PAM을 로컬로 구성했더라도 분기 없는 모드로 sudo해야 합니다.
충분히 조심하세요.
이를 비활성화하면 pam_session
설정 중인 PAM 세션에 따라 무언가가 중단될 수 있으며, pam_setcred
IPA, Kerberos 또는 PAM을 통해 발급되는 자격 증명 티켓에 의존하는 다른 것이 중단될 수도 있습니다. log_servers
자주 사용하지 않으면 !use_pty
대상 스크립트는 상위 스크립트에서 설정한 처음 3개의 파일 설명자를 상속합니다. 이 환경에서는 이것이 실제로 sudo가 "원격" 계정을 인증하는 것을 방해하는지 여부를 테스트할 수 없습니다.
더 나아가, 머신의 다른 모든 사용자에 대한 잠재적 피해를 최소화하려면 관련 사용자에게만 다음과 같은 특별한 권한을 부여해야 합니다.
Defaults: yourscriptuser !pam_session,!pam_setcred,!use_pty,!log_servers
현재 수행 중인 작업과 상위 스크립트에서 보내는 신호(예: 하위 스크립트 종료)가 작동하지 않을 수 있음을 이해하세요.
$ sudo cat /etc/sudoers | grep \!use_pty
Defaults: testuser !pam_session,!pam_setcred,!use_pty,!log_servers
# in one terminal:
$ sudo sh -c 'echo $$ && exec sleep 88888'
27749
# in other terminal:
$ kill -TERM 27749
kill: kill 27749 failed: operation not permitted
작업을 마친 후 또는 표준 입력 핸들에서 0바이트를 읽을 때(즉, 수시로 읽고 빈 읽기에서 종료되는) 첨자가 항상 종료되는지 확인하세요. 이는 파일이 닫혔음을 나타내는 표준 Unix 표시입니다( 이 경우 부모에서 오는 파이프의 경우) 이로 인해 부모가 종료될 때 여전히 실행 중인 동안 남아 있는 모든 자식이 올바르게 종료됩니다. 그렇지 않으면 코드에 따라 무기한으로 맴돌게 될 수도 있습니다(Sudo 핸들을 포크함).
답변3
Sudo는 지정한 명령을 실행하기 전에 포크합니다(편집: 항상 그런 것은 아닙니다. 다른 답변을 참조하세요). exec를 사용하여 포크를 실행 취소할 수 없습니다. bash에서 exec를 사용하면 포크가 완전히 방지되므로 bash에서 작동합니다. sudo otoh에는 이 기능이 없습니다. 그러나 프로그램을 백그라운드로 분기한 다음 중간 프로세스를 종료하면 다음과 같이 문제를 해결할 수 있습니다.
sudo -u www-data bash -c "php -r 'sleep(2); echo 5;' &"
여기에는 원래 상위 프로세스 정보가 손실되고 프로세스가 완료될 때까지 기다리지 않는 등 문제가 될 수도 있고 그렇지 않을 수도 있는 다른 부작용이 있습니다.
답변4
파일에 다음 줄을 추가하면 됩니다 sudoers
( sudo visudo
또는 를 사용하여 편집 sudo -e /etc/sudoers
).
# Run commands for all users with the exec system call directly.
# This may break some authentication systems or scripts.
Defaults !pam_session,!pam_setcred,!use_pty,!log_servers
# Run commands by "user" with the exec system call directly.
# This may also break authentication, but only for one user.
Defaults:user !pam_session,!pam_setcred,!use_pty,!log_servers
sudo
위의 변경을 수행하기 전에 실행 중이던 프로그램의 프로세스 목록 은 다음과 같습니다 .
$ sudo sleep 500 &
[1] 4453
$ ps -f T
UID PID PPID C STIME TTY STAT TIME CMD
root 4453 3478 0 00:16 pts/3 S 0:00 sudo sleep 500
root 4454 4453 0 00:16 pts/3 S 0:00 sleep 500
위와 같이 변경한 후:
$ sudo sleep 500 &
[1] 4479
$ ps -f T
UID PID PPID C STIME TTY STAT TIME CMD
root 4479 3478 0 00:18 pts/3 S 0:00 sleep 500
원하는 경우 다른 "기본값" 유형을 사용하여 "모든 호스트의 모든 사용자, 특정 호스트의 모든 사용자, 특정 사용자, 특정 명령 또는 특정 사용자로 실행되는 명령에 영향을 미칠" 수 있습니다. sudoers(5)
자세한 내용은 설명서를 참조하세요 .
@etosan이 언급했듯이 PAM을 비활성화하면 PAM 인증이 중단되고 특히 다중 사용자 및 원격 시스템에서 사용자와 관리자가 잠길 수 있습니다. @etosan 또 다른 이점은 원래 sudo 프로세스가 실행되지 않고 사용자를 대신하여 신호를 전달할 수 없기 때문에 sudo를 시작한 사용자로서 sudo로 시작한 프로그램을 더 이상 종료할 수 없다는 것입니다. 어떤 경우에는 이것이 보안 개선으로 간주될 수도 있지만 이 기능에 의존하는 프로그램이 중단될 수도 있습니다.
sudo 문서는 항상 포괄적이지 않고 이해하기 어려운 경우가 많으므로 중요하다면 소스를 읽어보는 것이 좋습니다.
내 시스템(Gentoo Linux 프로필 default/linux/amd64/17.1/no-multilib/hardened/selinux
)에서는 배포판의 기본 구성이 use_pty
및 기본적으로 비활성화되어 있으므로 log_servers
후자의 두 옵션은 필요하지 않습니다.
이 구성은 보안을 약화시킬 수도 있습니다 . sudo
다음을 다시 참조하세요 .sudoers(5)
pam_session On systems that use PAM for authentication, sudo will
create a new PAM session for the command to be run in.
Unless sudo is given the -i or -s options, PAM session
modules are run with the “silent” flag enabled. This
prevents last login information from being displayed
for every command on some systems. Disabling
pam_session may be needed on older PAM implementations
or on operating systems where opening a PAM session
changes the utmp or wtmp files. If PAM session support
is disabled, resource limits may not be updated for the
command being run. If pam_session, pam_setcred, and
use_pty are disabled, log_servers has not been set and
I/O logging has not been configured, sudo will execute
the command directly instead of running it as a child
process. This flag is on by default.
This setting is only supported by version 1.8.7 or
higher.
pam_setcred On systems that use PAM for authentication, sudo will
attempt to establish credentials for the target user by
default, if supported by the underlying authentication
system. One example of a credential is a Kerberos
ticket. If pam_session, pam_setcred, and use_pty are
disabled, log_servers has not been set and I/O logging
has not been configured, sudo will execute the command
directly instead of running it as a child process.
This flag is on by default.
This setting is only supported by version 1.8.8 or
higher.
(기본적 으로 use_pty
비활성화될 수 있음):
use_pty If set, and sudo is running in a terminal, the command
will be run in a pseudo-terminal (even if no I/O log‐
ging is being done). If the sudo process is not at‐
tached to a terminal, use_pty has no effect.
A malicious program run under sudo may be capable of
injecting commands into the user's terminal or running
a background process that retains access to the user's
terminal device even after the main program has fin‐
ished executing. By running the command in a separate
pseudo-terminal, this attack is no longer possible.
This flag is off by default.