로그인 후 SSH 사용자를 사전 정의 된 명령 세트로 제한하는 방법은 무엇입니까?


85

이것은 보안을위한 아이디어입니다. 우리 직원은 리눅스 서버의 일부 명령에 액세스 할 수 있지만 전부는 아닙니다. 예를 들어 로그 파일 ( less logfile) 에 액세스 하거나 다른 명령 ( shutdown.sh/ run.sh)을 시작할 수 있어야합니다 .

배경 정보:

모든 직원은 동일한 사용자 이름으로 서버에 액세스합니다. 당사 제품은 "일반"사용자 권한으로 실행되며 "설치"가 필요하지 않습니다. 사용자 디렉토리에 압축을 풀고 실행하십시오. 우리는 응용 프로그램이 "설치된"여러 서버를 관리합니다. 모든 컴퓨터에는 사용자가 있습니다.johndoe 있습니다. 직원들은 때때로 로그 파일에 액세스하여 확인하거나 수동으로 애플리케이션을 다시 시작하기 위해 명령 줄에서 애플리케이션에 액세스해야합니다. 일부 사용자 만 전체 명령 줄 액세스 권한을 갖습니다.

우리는 서버에서 ppk 인증을 사용하고 있습니다.

employee1이 로그 파일에만 액세스 할 수 있고 employee2도 X 등을 수행 할 수 있다면 좋을 것입니다.

해결책 : 해결책으로 나는 수락 된 답변에 command명시된 옵션을 사용합니다 . 일부 직원을 위해 실행할 수있는 유일한 파일이 될 저만의 작은 쉘 스크립트를 만들 것 입니다. 스크립트는 실행할 수있는 여러 명령을 제공하지만 다른 명령은 제공하지 않습니다. 여기에 설명 된대로 from에서 다음 매개 변수를 사용합니다 .authorized_keys

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@host

이것은 우리에게 충분한 보안입니다. 감사합니다, 커뮤니티!


표준 Linux ACL 권한 기반 보안이 충분하지 않습니까? 어떤 추가 기능이 필요합니까?
James Brady

22
끔찍한 생각이야, Marcel.
Vinko Vrsalovic

13
@Vinko, @PEZ : 배경 정보를 추가했습니다. "어리석은 생각"을 말하는 대신 가치있는 의견을 제공 할 수 있습니다. 더 나은 아이디어가 무엇이라고 생각하십니까?
Marcel

8
여러 사용자가 동일한 사용자 이름을 공유하는 것에 대한 변명의 여지가 없습니다.
Eldelshell

3
"나만의 작은 쉘 스크립트"? 꽤 위험한 것 같습니다. 당신이 전문가가 아니라면, 그것에서 풀 쉘로 탈출하는 많은 방법이있을 것입니다. 차라리 잘 작성되고 디버깅 및 유지 관리되는 프로그램을 신뢰합니다 (여러 언급 됨).
bortzmeyer

답변:


68

또한 키를 허용 가능한 명령으로 제한 할 수 있습니다 (authorized_keys 파일에서).

즉, 사용자는 ssh를 통해 로그인하지 않고 제한된 명령 세트를 가지지 만 오히려 ssh (예 : "ssh somehost bin / showlogfile")를 통해서만 해당 명령을 실행할 수 있습니다.


흥미로워 보입니다. 여러 명령을 정의 할 수 있습니까?
Marcel

12
이 기사에서는 authorized_keys 파일을 사용하는 여러 명령에 대한 몇 가지 옵션을 제공합니다. linuxjournal.com/article/8257
Bash

@ rd834 ... : 감사합니다. 나는 이것이 나에게 "좋은"해결책을 주었다고 생각한다 ... (질문에 추가됨). 나는이 대답을 "올바른"것으로 받아 들일 것입니다.
Marcel

11
O'Reilly SSH 책에는 SSH_ORIGINAL_COMMAND 환경 변수를 보는 스크립트를 설정하여 여러 명령을 허용하는 것을 포함하여이를 수행하는 방법에 대한 훌륭한 설명이 있습니다. oreilly.com/catalog/sshtdg/chapter/ch08.html
Alex Dupuy 2011

5
이 serverfault 답변 에는 내 보낸 SSH_ORIGINAL_COMMAND 변수를 사용하여 여러 명령을 허용하는 방법에 대한 좋은 팁이 있습니다.
MattBianco

32

sshrsh암호 파일에서 사용자의 셸 프로그램을 사용하여 명령을 실행함으로써 전통을 따릅니다 .

이것은 ssh어떤 식 으로든 구성을 포함하지 않고도이 문제를 해결할 수 있음을 의미합니다 .

사용자가 쉘 액세스 권한을 갖지 못하도록하려면 해당 사용자의 쉘을 스크립트로 바꾸십시오. 들여다 보면 /etc/passwd각 사용자에게 쉘 명령 인터프리터를 할당하는 필드가 있음을 알 수 있습니다. 스크립트는 대화식 로그인 ssh user@host 과 명령 모두에 대해 쉘로 사용됩니다 ssh user@host command arg ....

여기에 예가 있습니다. foo쉘이 스크립트 인 사용자 를 만들었습니다 . 스크립트는 메시지 my arguments are:와 인수 (각각 별도의 줄과 꺾쇠 괄호로 묶음)를 인쇄하고 종료합니다. 로그에는 인수가 없습니다. 다음은 발생합니다.

webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.

사용자가 명령을 실행하려고하면 다음과 같습니다.

webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>

우리의 "셸" -c은 전체 명령을 하나의 인수로 사용하여 스타일 호출을 받습니다./bin/sh 을받습니다.

보시다시피 이제 우리가 할 수있는 일은 스크립트를 추가로 개발하여 -c인수 로 호출 된 경우를 인식 한 다음 문자열을 구문 분석하는 것입니다 (예 : 패턴 일치). 허용되는 문자열은 재귀 적으로 호출하여 실제 쉘로 전달할 수 있습니다 /bin/bash -c <string>. 거부 사례는 오류 메시지를 인쇄하고 종료 할 수 있습니다 ( -c누락 된 사례 포함 ).

이 글을 쓰는 방법에주의해야합니다. 나는 매우 구체적인 것만 허용하고 다른 모든 것은 허용하지 않는 긍정적 인 일치 만 작성하는 것이 좋습니다.

참고 : 인 경우 다음 과 같이 명령 root에서 셸을 재정 의하여이 계정에 로그인 할 수 있습니다.susu -s /bin/bash foo . (선택의 대체 쉘.) 비 루트는 이것을 수행 할 수 없습니다.

다음은 예제 스크립트입니다. 사용자를 에서 저장소에 ssh대한 git액세스 용 으로 만 사용 하도록 제한합니다 /git.

#!/bin/sh

if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
  printf "interactive login not permitted\n"
  exit 1
fi

set -- $2

if [ $# != 2 ] ; then
  printf "wrong number of arguments\n"
  exit 1
fi

case "$1" in
  ( git-upload-pack | git-receive-pack )
    ;; # continue execution
  ( * )
    printf "command not allowed\n"
    exit 1
    ;;
esac

# Canonicalize the path name: we don't want escape out of
# git via ../ path components.

gitpath=$(readlink -f "$2")  # GNU Coreutils specific

case "$gitpath" in
  ( /git/* )
     ;; # continue execution
  ( * )
    printf "access denied outside of /git\n"
    exit 1
    ;;
esac

if ! [ -e "$gitpath" ] ; then
   printf "that git repo doesn't exist\n"
   exit 1
fi

"$1" "$gitpath"

물론 우리는 이러한 Git 프로그램 git-upload-packgit-receive-pack 구멍이 나 사용자에게 시스템에 대한 액세스를 제공합니다 해치를 탈출하지 않습니다.

그것은 이러한 종류의 제한 계획에 내재되어 있습니다. 사용자는 특정 보안 도메인에서 코드를 실행하도록 인증되었으며 해당 도메인을 하위 도메인으로 제한하는 제한을 두었습니다. 예를 들어 사용자가 vim특정 파일에 대해 명령 을 실행하여 편집 하도록 허용하면 사용자 는 :!sh[Enter].


6
진지하게, 이것은 매우 위험합니다. 내가 실행하는 것을 막는 것은 무엇입니까 git-receive-pack '/git/';dd if=/dev/urandom of=/dev/sda?
Yeti

@Yeti 여기에 명령 주입 구멍이 있습니까? 그것은 해결되어야합니다. 또한 내가 저지른 파일 패턴의 남용은 case나에게 맞지 않는 것 같습니다.
Kaz

1
예, /bin/bash -c "$2"안전하지 않습니다 (SQL 주입 작동 방식과 유사). PHP와 같은 "마법의 따옴표"로 문자열을 필터링 할 수 있습니다. 그러나 보안을 절대적으로 보장하는 쉬운 방법은 명령을 수동으로 호출 한 다음 큰 따옴표 안에 매개 변수를 전달하는 것입니다. 모든 것의 보안은 그 명령이 가장 약한 링크 (확인하기 더 어렵다)에 달려 있기 때문입니다. 귀하의 답변에 22 개의 업 보트가 있는지 확인하는 것이 가장 흥미롭지 만 아무도 이것을 알아 차리지 못했습니다.) 자신의 답변을 업데이트 하시겠습니까?
Yeti

1
@Yeti 예; 난 그냥했다. 나는 스크립트를 -c 인수를 나누는 것으로 교체 한 set다음 처음 두 단어 만 가져옵니다. 첫 번째는 허용 된 git-명령이어야하고 두 번째는 허용 된 접두사에 대해 확인되고 존재 여부를 확인하는 정규화 된 경로 여야합니다. 이것을 깰 방법을 생각할 수 있습니까?
Kaz

1
누군가 주어진 명령에 대해 별칭을 만들거나 명령을 재정의하지 않는 한, Bash 큰 따옴표는 안전해야합니다 (그렇지 않으면 Bash의 버그입니다).
Yeti

15

찾고있는 것은 Restricted Shell 이라고 합니다. Bash는 사용자가 자신의 홈 디렉토리에있는 명령 만 실행할 수 있고 다른 디렉토리로 이동할 수없는 모드를 제공하므로 충분할 수 있습니다.

이 스레드 는 약간 날짜가있는 경우 매우 예시적인 것으로 나타났습니다 .


1
사용자가 less 프롬프트에서 "! / bin / sh"또는 이와 같은 작업을 수행하면 어떻게됩니까?
PEZ

3
@Ubersoldat : ​​모든 게시물에서 공격성을 낮추고 성장 시키십시오. 그는 제한이 bash 또는 자식 프로세스에만 적용되는지 여부를 묻고있었습니다 (그리고 그의 질문에 답하기 위해 그렇지 않은 것으로 밝혀졌습니다).

제한된 쉘의 주요 문제점은 보안을 위해 .profile 또는 .bashrc를 사용하여 PATH를 제한하고 내장 기능을 비활성화하는 등의 작업을해야한다는 것입니다. 그러나 이러한 파일은 대화 형 쉘에 대해서만 호출됩니다. 사용자가 ssh를 사용하여 원격 명령을 실행하면 호출되지 않습니다. 이렇게하면 SHELL = / bin / rbash 계정에 ssh 액세스 권한이있는 사용자가 "ssh remotehost bash"와 같은 작업을 수행하여 비대화 형이지만 제한되지 않은 셸을 얻을 수 있습니다. HD가 제안한대로 SSH 강제 명령이 필요하지만 PEZ가 요청한대로 쉘 이스케이프로부터 보호 할 수 있습니다 (PATH가 잠기면 기본적으로 / bin : / usr / bin 포함).
Alex Dupuy

2
다시 가져가, bash sshd에서 비대화 형으로 실행될 때 .bashrc (.profile이 아님)를 호출 할 것이다 . 그러나 PATH를 명시 적으로 설정하고 .bashrc에서 내장 및 별칭을 비활성화해야합니다. PATH 또는 .ssh / 또는 .bashrc에없는 하위 디렉토리로 변경하는 것도 좋은 생각입니다. 임의의 파일에 쓸 수있는 명령이 있으면 문제가 발생합니다. 항상 명확하지는 않습니다. 예를 들어 sed 'w'명령을 사용하여 .bashrc를 덮어 쓰고 중단 할 수 있습니다. chroot jail은 사용할 수 있다면 항상 더 안전하며 ssh 강제 명령은 더 제한됩니다.
Alex Dupuy 2011

4

제한된 쉘인`rssh '를 얻어야합니다.

위에서 언급 한 제한 가이드를 따를 수 있으며, 모두 이해하기 쉽고 따르기 쉽습니다. `chroot jail '이라는 용어를 이해하고 sshd / terminal 구성을 효과적으로 구현하는 방법 등을 이해합니다.

대부분의 사용자가 sshd를 통해 터미널에 액세스하므로 SSH를 통해 특정 제한을 적용하려면 SSH 데몬 구성 파일 인 sshd_conifg도 살펴 봐야합니다. 그러나 조심하십시오. 잘못된 구성의 결과는 아마도 다소 끔찍할 수 있으므로 구현하려는 것을 올바르게 이해하십시오.


1
참고 것을 pizzashack.org/rssh이 우수한 허용 할 특별한 경우에 (아마도 최고의) 솔루션은 SCP / SFTP / rdist를 / rsync를 / CVS (및 chroot로 외부 아무것도에 액세스 할 필요가 없습니다) - 그러나 , 사용자가 로그 파일을보고 특정 실행 / 종료 스크립트를 실행할 수 있기를 원했던 원래 포스터의 일반적인 질문을 해결하지 못합니다.
Alex Dupuy

2
rsshDebian Buster에서 제거되었습니다. 새로운 매력은 GNU 러시 라고 생각합니다 .
토마스

1
내가 믿는 @Thomas rssh 지금은 전혀 관리가되지 않고 있으며, 알려진 보안 문제가 있습니다 sourceforge.net/p/rssh/mailman/message/36519118
최대 Barraclough

4

자신 만의 로그인 쉘을 작성하지 않는 이유는 무엇입니까? 이를 위해 Bash를 사용하는 것은 매우 간단하지만 모든 언어를 사용할 수 있습니다.

Bash의 예

자주 사용하는 편집기를 사용하여 파일을 만듭니다 /root/rbash.sh(이름 또는 경로가 될 수 있지만 chown root:root및 이어야 함 chmod 700).

#!/bin/bash

commands=("man" "pwd" "ls" "whoami")
timestamp(){ date +'%Y-%m-%s %H:%M:%S'; }
log(){ echo -e "$(timestamp)\t$1\t$(whoami)\t$2" > /var/log/rbash.log; }
trycmd()
{
    # Provide an option to exit the shell
    if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
    then
        exit
        
    # You can do exact string matching for some alias:
    elif [[ "$ln" == "help" ]]
    then
        echo "Type exit or q to quit."
        echo "Commands you can use:"
        echo "  help"
        echo "  echo"
        echo "${commands[@]}" | tr ' ' '\n' | awk '{print "  " $0}'
    
    # You can use custom regular expression matching:
    elif [[ "$ln" =~ ^echo\ .*$ ]]
    then
        ln="${ln:5}"
        echo "$ln" # Beware, these double quotes are important to prevent malicious injection
        
        # For example, optionally you can log this command
        log COMMAND "echo $ln"
    
    # Or you could even check an array of commands:
    else
        ok=false
        for cmd in "${commands[@]}"
        do
            if [[ "$cmd" == "$ln" ]]
            then
                ok=true
            fi
        done
        if $ok
        then
            $ln
        else
            log DENIED "$cmd"
        fi
    fi
}

# Optionally show a friendly welcome-message with instructions since it is a custom shell
echo "$(timestamp) Welcome, $(whoami). Type 'help' for information."

# Optionally log the login
log LOGIN "$@"

# Optionally log the logout
trap "trap=\"\";log LOGOUT;exit" EXIT

# Optionally check for '-c custom_command' arguments passed directly to shell
# Then you can also use ssh user@host custom_command, which will execute /root/rbash.sh
if [[ "$1" == "-c" ]]
then
    shift
    trycmd "$@"
else
    while echo -n "> " && read ln
    do
        trycmd "$ln"
    done
fi

이 실행 파일을 로그인 쉘로 설정하기 만하면됩니다. 예를 들어, 편집하여 /etc/passwd파일을 해당 사용자의 현재 로그인 쉘 교체 /bin/bash와를 /root/rbash.sh.

이것은 단순한 예일 뿐이지 만 원하는만큼 발전시킬 수 있습니다. 아이디어가 있습니다. 자신과 유일한 사용자의 로그인 셸을 변경하여 자신을 잠그지 않도록주의하십시오. 그리고 항상 이상한 기호와 명령을 테스트하여 실제로 안전한지 확인하십시오.

다음을 사용하여 테스트 할 수 있습니다 su -s /root/rbash.sh..

주의 하고 전체 명령과 일치하는지 확인하고 와일드 카드에주의하십시오! 더 나은 같은 배쉬 - 문자 제외 ;, &, &&, ||,$ , 및 역 따옴표 확신 할 수 있습니다.

사용자에게주는 자유에 따라 이보다 훨씬 더 안전하지 않습니다. 몇 가지 관련 명령에만 액세스 할 수있는 사용자를 만들기 만하면되는 경우가 많았는데,이 경우 정말 더 나은 솔루션입니다. 그러나 더 많은 자유를 원하십니까, 감옥과 권한이 더 적절할 수 있습니다. 실수는 쉽게 만들어지며 이미 너무 늦었을 때만 알아 차립니다.


저는이 접근 방식을 정말 좋아했습니다. "service httpd restart"와 같은 여러 단어로 된 명령을 어떻게 처리 할 수 ​​있는지 알고 계십니까?
Farzan

2
당신은 예를 들어, 변수에 명령을 실행할 수 있습니다 @Farzan ln="service httpd restart"로, : ${ln[@]}. 여전히 보안 문제에 대해 생각해야합니다. 이러한 경우에는 영숫자 문자와 공백 만 허용하는 화이트리스트가 유용 할 것입니다. 그러나 다음과 같이 할 수도 있습니다. if [[ "$ln" == "restart-httpd"];then service httpd restart;fi, 이와 같은 간단한 명령으로 작업하십시오.
Yeti

/root/rbash.sh: Permission denied 나는 또한 chmod 777을 시도했습니다
Christian

@Christian, 당신은 추가 않았다 /root/rbash.sh/etc/shells? 분포에 따라 다릅니다. 또한 일시적으로을 비활성화 selinux하고 /var/log.
Yeti

@yeti no, / root에 추가하도록 설명되었습니다. :) 지금 시도하겠습니다.
기독교

1

설정을 살펴보고 싶을 수도 있습니다. 감옥 .


질문에는 'linux'태그가 있습니다. 감옥은 FreeBSD에만 국한되지 않습니까?
Max Barraclough

1

GNU Rush 는이를 수행하는 가장 유연하고 안전한 방법 일 수 있습니다.

GNU Rush는 svn 또는 git 리포지토리, scp 등과 같은 리소스에 대한 제한된 원격 액세스를 제공하는 사이트를 위해 설계된 제한된 사용자 셸입니다. GNU Rush는 정교한 구성 파일을 사용하여 사용자가 실행하는 명령 줄과 가상 메모리, CPU 시간 등과 같은 시스템 리소스 사용을 완벽하게 제어 할 수 있습니다.


0

이를 확인하는 또 다른 방법은 POSIX ACL을 사용하는 것입니다. 파일 시스템에서 지원해야하지만 Windows에서 동일한 제어 권한을 갖는 것과 동일한 방식으로 Linux에서 모든 명령을 세밀하게 조정할 수 있습니다 (더 좋은 UI없이 ). 링크

살펴볼 또 다른 사항은 PolicyKit 입니다.

현재로서는 확실히 Linux의 장점이 아니기 때문에 모든 것이 작동하도록하려면 인터넷 검색을 많이해야합니다.


0

[공개 : 아래에 설명 된 sshdo를 작성했습니다.]

로그인을 대화 형으로하려면 제한된 쉘을 설정하는 것이 정답 일 것입니다. 그러나 허용하려는 실제 명령 세트가 있고 (다른 것은 없음) 이러한 명령이 ssh (예 : ssh user @ host cmd arg blah blah)를 통해 개별적으로 실행되는 것이 괜찮다면 ssh가 필요할 수 있습니다. 이는 명령이 클라이언트 측에서 스크립팅되고 사용자가 실제로 ssh 명령을 입력 할 필요가 없을 때 유용합니다.

이를위한 sshdo라는 프로그램이 있습니다. 들어오는 ssh 연결을 통해 실행할 수있는 명령을 제어합니다. 다음에서 다운로드 할 수 있습니다.

http://raf.org/sshdo/ (여기에서 매뉴얼 페이지 읽기) https://github.com/raforg/sshdo/

시도 된 모든 명령을 허용하는 교육 모드와 학습 된 명령을 영구적으로 허용하는 데 필요한 구성을 생성하는 --learn 옵션이 있습니다. 그런 다음 훈련 모드를 끌 수 있으며 다른 명령은 실행되지 않습니다.

또한 시간이 지남에 따라 요구 사항이 변경 될 때 엄격한 최소 권한을 유지하기 위해 더 이상 사용되지 않는 명령의 허용을 중지하는 --unlearn 옵션이 있습니다.

그것이 허용하는 것에 대해 매우 까다 롭습니다. 인수가있는 명령은 허용되지 않습니다. 완전한 쉘 명령 만 허용 될 수 있습니다.

그러나 명령 줄에 나타나는 숫자 (예 : 시퀀스 번호 또는 날짜 / 시간 스탬프)에서만 다른 유사한 명령을 나타내는 간단한 패턴을 지원합니다.

ssh 명령에 대한 방화벽 또는 화이트리스트 제어와 같습니다.

그리고 다른 사용자에게 허용되는 다른 명령을 지원합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.