다음과 같이 bash 프롬프트에 sudo 세션 상태를 추가할 수 있습니다.
function sudo_active() {
if sudo -n /bin/true 2> /dev/null
then
printf '(sudo) '
fi
}
PS1="$PS1"'$(sudo_active)'
이렇게 하면 일련의 sudo 명령을 실행할 수 있고 sudo 세션이 여전히 활성 상태인지 알 수 있습니다. 세션을 일찍 종료하거나 sudo -k
, 셸을 닫거나, 주의 사항을 기억하는 등의 방법을 사용할 수 있습니다.
이 접근 방식의 한 가지 문제점은 sudo 권한 없이 새 프롬프트가 실행될 때마다 시스템 로그에 다음과 같은 메시지가 추가된다는 것입니다.
sudo[25653]: myusername : a password is required ; TTY=pts/13 ; PWD=/home/myusername/ ; USER=root ; COMMAND=/bin/true
또 다른 문제는 이것이 sudo
매번 프롬프트에서 명령을 실행하기 때문에 passwd_timeout
필요한 명령을 실행하지 않더라도 명령을 실행할 때마다( 값에 따라) 시간 초과가 다시 연장된다는 것입니다 sudo
.
sudo 세션이 여전히 활성 상태인지 테스트하고 부작용으로 세션을 지속적으로 다시 확장하지 않고 이를 bash 프롬프트에 표시하는 방법이 있습니까?
답변1
sudo가 각 사용자에 대해 생성하는 타임스탬프 파일을 사용하여 해당 사용자가 sudo 명령을 사용한 시간을 찾을 수 있습니다. 구성된 시간(기본값 5분)보다 길면 timestamp_timeout
새 sudo에 비밀번호가 필요합니다.
각 사용자의 파일은 /var/run/sudo/ts/
(내 시스템에서) 아래에 생성됩니다. man sudoers
소스에서 볼 수 있듯이 형식은 부분에 설명되어 있습니다 .타임스탬프.c그리고check.h이는 struct timestamp_entry_v1
struct 또는 최신 struct 로 설명되는 여러 레코드로 구성됩니다 struct timestamp_entry
.
Git 버전은 이전 시스템의 해당 소스보다 최신이므로 이전 구조 버전 1을 사용하고 있습니다. 추가 필드가 있는 새 버전 2가 필요할 수 있습니다.
다음은 하드와이어된 사용자의 기록을 덤프하는 최소한의 C 프로그램입니다:
/* https://unix.stackexchange.com/a/595473/119298
* struct from
* https://github.com/sudo-project/sudo/blob/master/plugins/sudoers/check.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TS_VERSION 1
/* Time stamp entry types */
#define TS_GLOBAL 0x01
#define TS_TTY 0x02
#define TS_PPID 0x03
#define TS_LOCKEXCL 0x04
/* Time stamp flags */
#define TS_DISABLED 0x01 /* entry disabled */
#define TS_ANYUID 0x02 /* ignore uid, only valid in the key */
struct timestamp_entry {
unsigned short version; /* version number */
unsigned short size; /* entry size */
unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
unsigned short flags; /* TS_DISABLED, TS_ANYUID */
uid_t auth_uid; /* uid to authenticate as */
pid_t sid; /* session ID associated with tty/ppid */
struct timespec ts; /* timestamp (CLOCK_MONOTONIC) */
union {
dev_t ttydev; /* tty device number */
pid_t ppid; /* parent pid */
} u;
};
void main(int argc, char **argv){
struct timestamp_entry entry;
struct timespec now;
int fd = open("/var/run/sudo/ts/meuh",O_RDONLY);
if(fd<0)exit(1);
clock_gettime(CLOCK_MONOTONIC, &now);
while(read(fd,&entry,sizeof(entry))==sizeof(entry)){
printf("type=%d flags=%d uid=%d sid=%d elapsedtime=%d\n",
entry.type, entry.flags, entry.auth_uid, entry.sid,
entry.ts.tv_sec-now.tv_sec);
}
exit(0);
}
내 시스템에서 이 setuid 루트를 컴파일하고 실행하면 다음과 같은 줄이 표시됩니다.
type=4 flags=0 uid=0 sid=0 elapsedtime=-4763540
type=2 flags=1 uid=1000 sid=7003 elapsedtime=-4763540
type=2 flags=0 uid=1000 sid=4378 elapsedtime=-12
유형 4의 첫 번째 항목은 레코드를 잠그는 데 사용됩니다. 다른 라인은 tty별로 될 수 있습니다. 플래그 1은 항목이 비활성화되었음을 나타냅니다(예: 로 인해 sudo -k
). 마지막 줄은 12초 전에 프로세스 4378에서 sudo 명령을 실행한 uid 1000입니다. 5*60초 미만이므로 추가 sudo에는 아직 비밀번호가 필요하지 않습니다.