루트가 탈출할 수 없는 chroot를 생성하기 위해 Linux의 파일 시스템 내에서 chdir("..")을 사용하는 방법은 무엇입니까?

루트가 탈출할 수 없는 chroot를 생성하기 위해 Linux의 파일 시스템 내에서 chdir("..")을 사용하는 방법은 무엇입니까?

/var/mychoot와 동일한 파일 시스템에 디렉토리가 있고 /으로 프로그램을 시작했으므로 프로그램은 EUID 0으로 실행됩니다 /var/mychroot/prog.sudo chroot /var/mychroot /prog

프로그램이 실행되면chdir("..") 이스케이프 기술, 그러면 chroot를 탈출하여 내부의 모든 것을 볼 수 있습니다 /. (Linux 4.18에서 이것을 확인했습니다.)

나는 그런 탈출을 막고 싶다. 실제로 저는 다양한 chroot 이스케이프를 방지하고 싶지만 이 질문에서는 어떻게 해야 하는지에만 관심이 있습니다.chdir("..") 이스케이프 기술이는 최신 Linux 시스템에서는 방지할 수 있습니다. 이를 위해 대안을 찾고 있습니다.chroot(2)시스템 호출.

두 가지 해결책을 찾았습니다.피벗 루트그리고MS_모바일, 그러나 /var/mychroot마운트 지점인 경우에만 작동하므로 /var/mychroot파일 시스템의 하위 디렉터리인 경우에는 실패합니다 /. 이 경우 다른 해결책이 있습니까?

LD_PRELOAD기술 사용을 피하고 ( LD_PRELOAD정적으로 링크된 실행 파일은 영향을 받지 않으므로) 기술을 사용하고 싶습니다.트랙(2)(그렇다면 나는 stracechroot에서 실행할 수 없고,트랙(2)프로세스가 충돌하거나 정지됨) 및 진정한 가상화(예: 성능 오버헤드 및 유연성이 떨어지는 메모리 구성으로 인해)를 올바르게 수행하는 것은 까다롭습니다.

요약하자면 다음이 필요합니다.

  • 에 대한 대안chroot(2)시스템 호출,
  • 루트는 이를 사용하여 루트(EUID 0)로 실행되는 프로세스를 제한합니다.
  • 파일 시스템의 하위 디렉토리로 /,
  • 이는 방지합니다chdir("..") 이스케이프 기술,
  • 사용하지 LD_PRELOAD않거나
  • 트랙(2)또는
  • 가상화(예: Xen, KVM 또는 QEMU)
  • 최신 Linux 시스템에서 실행되며,
  • 패치된 커널이 있거나 없는 경우.

존재합니까?

답변1

언급한 특정 이스케이프 기술을 방지하려면 잠긴 후 chdir("..")다시 실행하는 기능을 포기 하면 됩니다. 이스케이프 기술을 다시 호출해야 하므로 이를 차단하는 것만으로도 작동하지 않게 됩니다.chroot(2)/var/mychrootchroot()

Linux 기능을 사용하여 이 작업을 수행할 수 있습니다. CAP_SYS_CHROOT원하는 기능을 제거하기만 하면 됩니다 chroot(2).

예를 들어:

outside# chroot /var/mychroot
inside# capsh --drop=cap_sys_chroot --
inside# ./escape_chroot
chroot(baz): Operation not permitted

(chroot 내부의 두 번째 프롬프트는 생성된 쉘에서 나옵니다 capsh. 예를 들어 를 사용하여 다른 명령을 실행하도록 할 수 있습니다 capsh --drop=cap_sys_chroot -- -c 'exec ./escape_chroot'.)


그러나 더 나은 기술은 예방할 수 없는 pivot_root다른 많은 공격을 예방할 수 있기 때문에 만 사용하는 것입니다.chroot(2)

마운트 지점인 경우 에만 작동한다고 언급했지만 /var/mychroot단순히 바인드 마운트하여 마운트 지점으로 만들 수 있습니다.

pivot_root감옥을 생성하기 위해 마운트 네임스페이스를 생성해야 한다는 점에 유의하십시오 . 그렇지 않으면 파일 시스템에 있는 모든 프로세스의 루트 디렉터리를 변경하려고 시도할 것입니다. 이는 여러분이 원하는 것과 다를 가능성이 높습니다.

따라서 전체 순서는 다음과 같습니다.

outside# unshare -m
outside# mount --bind /var/mychroot /var/mychroot
outside# cd /var/mychroot
outside# mkdir old_root
outside# pivot_root . old_root
limbo# exec chroot .
inside# umount /old_root

(다시 말하지만, 이러한 명령 중 다수는 새 셸을 생성합니다. unshare그렇게 하면 자체적으로 수행됩니다 chroot. 명령을 추가 인수로 전달하여 이러한 문제를 해결할 수 있습니다. 경우에 따라 sh -c '...'전체 스크립트를 전달할 수도 있습니다.)

이 시점에서 당신은 별도의 마운트 네임스페이스에 있는 감옥 안에 있습니다 . 이것이 단지 원래 루트(별도의 장치나 루프 장치에 대한 마운트가 아닌) pivot_root라는 사실이 실제로 작동을 방해하지는 않습니다. /var/mychroot마운트를 중간에 바인딩합니다.

이스케이프 코드를 실행하면 감옥이 예상대로 작동하는 것을 볼 수 있습니다(이스케이프 코드에 다르게 명시되어 있음에도 불구하고).

inside# touch /inside_jail
inside# ./escape_chroot
Exploit seems to work. =)
inside# ls -ld /inside_jail /old_root
-rw-r--r--.  1 0 0    0 Jan  5 23:45 /inside_jail
dr-xr-xr-x. 20 0 0 4096 Jul  5 23:45 /old_root

보시다시피, 여전히 감옥 안에 있습니다... 익스플로잇 코드는 약간 순진하며 ( chroot, chdir) 작업이 성공하면 감옥을 탈출하기에 충분하다고 가정하지만 그렇지 않습니다. .

chroot따라서 이 기술을 사용하여 내부 작업을 차단하기 위해 Linux 기능을 사용할 필요가 없고 더 우수한 감옥을 만드는 것을 고려해 보십시오 (예 chroot: 감옥에서 실제로 수행하려는 작업보다 더 중요한 추가 기능을 만드는 등).

답변2

/var/mychroot가 마운트 지점인 경우에만 작동하므로 /var/mychroot가 / 파일 시스템의 하위 디렉터리인 경우에는 실패합니다.

어떤 디렉토리든 마운트 지점으로 설정할 수 있습니다 mount --rbind /var/mychoot /var/mychoot.

이 단계와 필요한 기타 단계는 여기에서 다룹니다.

Linux 네임스페이스를 사용하여 chroot를 수행하는 방법은 무엇입니까?

사실 나는 다양한 chroot 탈출을 막고 싶습니다.

위 내용을 사용자 네임스페이스와 결합합니다.

또는, seccomp. mount()예를 들어 Docker가 포함된 프로세스 호출을 방지하는 방법은 다음과 같습니다. (블록 장치를 두 번째로 마운트하면 파일 시스템에 대한 두 번째 보기가 표시되며 이는 다소 탈출구로 간주됩니다.) Docker에서 허용하는 시스템 호출 목록을 복사하세요. 루트를 탈출하는 방법은 다양합니다.

https://docs.docker.com/engine/security/seccomp/

https://github.com/moby/moby/blob/master/profiles/seccomp/default.json

관련 정보