오늘 할 일 시네보 강의 / 실습 / 과제 Stack을 이용해서 알고리즘 오답 다시 풀어보기 매일 토익(예상점수 660) IT 운용 체제 변화를 위한 데브옵스 DevOps - 1단원 마저 읽고 내용 정리해서 노션에 작성 유클리드 호제법 찾아보기 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 2단원 복습, 3단원 실습
Set_UID 프로그램은 실행하는 동안 소유자 권한을 얻는다. 루트 소유의 파일이면 루트 권한을 가지므로 강력한 힘을 가진다. 예를 들어, 원래 /etc/shadow는 패스워드가 담긴 파일이기 때문에 접근할 수 없다. 그런데 Set_UID로 설정한 cat과 동일한 기능을 하는 파일을 만들어 수행하면 들여다볼 수가 있다.
하지만 그만큼 보안상 취약점이 될 수도 있다. Set_UID를 이용한 보안 공격을 해보려고 한다.
euid가 0이라는 것은 현재 root에서 실행되고 있다는 뜻이다. 그런데, uid 현재 user는 seed이다. Set-UID를 이용할 땐 euid와 uid가 다르다.
추가로, Set_UID를 설정할 때는 chmod에서 앞에 special bit인 4를 붙여주면 된다. ex) sudo chmod 4755 test
이 밖에도 필요한 기초적인 지식들을 알고 가자면, chmod : 권한 부여 chown : 소유주 변경 chgrp : 소유 그룹 변경
권한 부여할 때 rwx는 소유자 - 그룹 - 유저 순이다. 4 : read 2 : write 1 : exception
2^2, 2^1, 2^0을 더해서 원하는 대로 권한을 부여할 수 있다.
shell을 이용해서 보안 취약점을 공격할 수도 있다.
사용자가 메모리나 파일에 접근하려면, OS 커널에 요청을 하고, OS 커널은 사용자 서비스를 실행하는 방식(systemcall)으로 작동한다.
system(command) 함수는 "/bin/sh -c command" 방식으로 실행한다. 즉, /bin/sh를 실행하고 해당 쉘에 comand를 요청한다. 만약 task2.c가 Set-UID라면, 일반 유저도 접근할 수 있으나 root 권한으로 새로운 shell을 실행시키기 때문에 해당 파일을 이용해서 root 권한으로 악의적인 행동을 취할 수도 있다.
그런데, 컴파일 해서 수행해본 결과, 새로 실행된 쉘은 root로 실행되지 않는다. /bin/sh가 뜻하는 /bin/dash 쉘에서는 set-UID 프로세스에서 실행된 것을 감지하면 euid를 ruid로 즉시 다운그레이드해서 권한을 뺏어가기 때문이다. 그렇다면 zsh의 경우에는 어떨까?
공격 3. 환경변수를 이용한 공격
linux 명령어 ls는 어디서든 사용이 가능하다. 원래 경로는 /bin/ls 인데 어떻게 어디서든 실행되느냐 하면 환경변수 편집이 돼있기 때문이다. 이번엔 그 환경변수를 수정해서 공격을 해보려고 한다.
그렇다면 이 환경변수를 수정해서 ls라는 이름을 가진 악성코드를 만들고 사용자가 ls를 입력한다면 해당 코드를 실행하게 해서 공격을 할 수도 있을 것이다. 심지어 ls를 cp한 코드를 작성해 Set-UID 상태로 실행한다면 root 권한인 상태이다.
이번엔 ls 기능을 수행하는 ls를 만들고, shell을 실행시키는 ls도 만들어서 환경 변수를 수정해서 /bin/ls를 실행시키는 것이 아닌, shell을 실행시키는 ls라는 파일을 실행시키도록 할 것이다.
환경 변수를 추가해 주자.
이제 Set-UID 설정이 된 task3를 실행해 보자.
여기서 환경변수 설정을 되돌리고 싶으면 그냥 터미널을 다시 실행시키면 된다.
공격4. system()과 execve()를 이용한 외부 프로그램 호출
execve()를 이용하면 system()과 달리, 쉘을 호출하지 않기 때문에 문제가 없다.
원래는 seed(user)가 접근할 수 없는 test.txt를 수정할 수 있게 해보자.
linux 환경에서 ;는 다음 명령을 실행하라는 의미이다. 따라서, " a; b"는 a를 실행하고 b를 실행하라는 의미인데, task4는 Set-UID이므로 실행할 땐 root 권한을 가지고 있다. 따라서 바로 지울 수 있다.
이번엔 system(command)가 아니라, execve(v[0], v, 0);으로 수정해서 수행해 보았다.
execve는 command로 받은 다음에 수행하는 게 아니라, 데이터로 넘기기 때문이다. 따라서 다음과 같이 코딩할 경우가 있을 때는 execve로 하는 것을 권장한다.