세션을 확장하지 않고 PS1에 sudo 세션 상태 추가

세션을 확장하지 않고 PS1에 sudo 세션 상태 추가

다음과 같이 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_v1struct 또는 최신 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에는 아직 비밀번호가 필요하지 않습니다.

관련 정보