모든 사용자가 실행할 수 있는 Bob 사용자의 취약한 SUID 프로그램이 있다고 가정해 보겠습니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
const char* s = getenv("USER"); // for debugging
printf("%s\n", s); // for debugging
char cmd[256] = "/home/bob/hello.sh $USER"; //hello.sh prints "Hello world"
execl("/bin/bash", "bash", "-p", "-c", cmd, NULL);
return 0;
}
Bob만이 볼 수 있는 파일을 읽기 위해 실행되는 명령에 USER 환경 변수가 추가되어 있다는 사실을 활용하고 싶습니다. 예를 들어, USER를 다음으로 설정하면";cat /home/bob/secret-file"
env USER=";cat /home/bob/secret-file" ./program
이것은 실행되지 않고 다음과 같이 반환됩니다.
;cat /home/bob/secret-file
Hello world
USER 환경 변수가 변경되더라도 두 번째 명령은 실행되지 않습니다.
C 코드를 편집하지 않고 USER 환경 변수를 사용하여 "cat"과 같은 명령을 실행하여 bob의 권한으로(프로그램이 SUID이므로) 실행하고 bob만 볼 수 있는 파일을 보려면 어떻게 해야 합니까?
답변1
당신이 하고 싶은 일은 불가능합니다. 이는 C 또는 SUID와 관련이 없지만 쉘이 변수를 확장하는 방법과 관련이 있습니다.
셸의 입력을 개별 셸 명령으로 구문 분석합니다.앞으로환경 변수를 확장합니다. 변수의 내용은아니요쉘 구문에 따라 해석합니다(그렇지 않으면 foo='$foo' ; : $foo
무한 루프가 됩니다). 이는 명령줄에 변수를 삽입하는 작업을 별도의 명령줄로 분할할 수 없음을 의미합니다. 변수가 인용되지 않은 경우 이는 단순히 변수의 내용이 공백에서 명령의 여러 매개변수로 분할될 수 있음을 의미합니다. 이는 일종의 악용 가능한 취약점을 생성할 수도 있고 생성하지 않을 수도 있지만 직접적인 셸 주입은 아닙니다.
hello.sh
스크립트를 다음으로 바꾸는 경우 :
#!/bin/sh
i=1
for arg in "$@"; do
echo "argument #$i: [[$arg]]"
i="$(expr "$i" + 1)"
done
;cat
첫 번째 및 두 번째 매개변수를 사용하여 호출된다는 것을 알 수 있습니다 /home/bob/secret-file
. 쉘은 이를 ;
명령 구분 기호로 해석하지 않고 그냥 전달합니다.