ragdo11 2025. 5. 7. 23:48

주요정보통신기반 웹 취약 분석 평가 방법 네 번째 항목인 운영체제 명령 실행(OS Command Execution or OS Command Injection/OC)이다.

개인적으로 꼭 한번 다뤄보고 싶었던 취약점인데 미루다가 다행히 주통기반 공부를 하면서 만나게 되서 기쁘다!

이참에 제대로 공부해보자.

 

OC 취약점은 system, exec 등 명령어 실행 함수를 사용하는 곳에서 발견된다. system 함수 등은 입력받은 인자를 command로써 실행시키게 되는데 여기에 OS Command 취약점이 존재한다면 공격자가 이를 악용해 입력을 임의의 운영체제 명령으로 실행할 수 있는 취약점이다.

OC 공격에 성공하기만 한다면 근본적으로 흔들 수 있는 방법인 만큼 민감한 정보의 탈취나 웹 애플리케이션의 막대한 손상, 신뢰 관계를 이용한 공격의 전환, 웹 애플리케이션의 권한이 높을 시에는 임의의 파일 삭제나 업로드, 특정 사용자의 권한 상승, 웹 서버를 닫는 등의 강력한 공격을 할 수 있다.

 

솔직히 공부하기 전까지는 이거 도대체 왜 발생하는 것인가 라는 생각이 막연히 들었다. 사용자 입력을 명령으로 받는 형태(아니면 파라미터로 system 등의 함수에 전달하는 형태)가 어디에 쓰인다고 그런 위험성이 있는 함수를 웹 애플리케이션에 사용하는 것일까?

 

당연하겠지만 위험성만 따르면 낙후된 형태의 코드가 아닌 이상 OC 공격이 굉장히 희박하게 발생할 것이다. 분명 용이하게 사용되는 부분이 있기 때문에 포기를 할 수가 없을 테니까.

 

system 등의 함수는 쉘에 직접 명령을 하는 기능을 하는 함수인 만큼 운영체제가 제공하는 서비스나 외부 스크립트를 실행하기 위해 사용된다. 이러한 기능이 필요하다면 일반적인 코드로는 서비스를 제공할 수 없기 때문에 운영체제 커널 레벨에서 실행시켜 제공을 하기 위해 사용되는 것이다.

 

전반적으로 알아봤으니 실습을 통해 공격 방식과 방어법을 알아보자!

OC 취약점을 실습하기 위해 간략하게 구성된 공간(?)이다.

 

<?php
$file=['file'];
system("cat ./upload/".$file);
?>

ㅋㅋㅋ 진짜 간략함. 대충 사용자 파일을 지정하면 system 함수가 명령을 구성해서 화면에 보여주는 시나리오라고 생각해주길 바란다. 그냥 연습해보기 위한 거니까~

 

이런 식으로 text.txt 파일을 지정했을 때 화면에 보여진다. 다만 system 함수가 사용자의 입력을 전혀 검증하지 않고 쉘로 명령어를 뿌려주고 있으니 이를 이용하여 다른 명령어를 실행할 수 있다.

 

잉 그런데 만약 저기에 운영체제 명령어를 구성하려고 ls 같은 것을 시도해봐도 system 함수에는 cat ./upload/ls 가 전달되어 원하는 대로 동작하지 않을꺼잖아!!

여기서 알아봐야 하는 것은 리눅스는 다중 명령어를 지원한다는 점이다. ; / & / | / && / || 를 통해서 연속적인 명령어의 실행이 가능해진다.

 

먼저 세미콜론(;) [ 명령1 ; 명령2 ... ]

세미콜론은 앞 명령의 성공·실패와 관계없이 뒤의 명령을 실행해준다.

 

더블 앰퍼샌드(&&) [ 명령1 && 명령2 ... ]

더블 앰퍼샌드는 앞 명령이 성공해야만 뒤의 명령이 실행된다.

 

더블 파이프(||) [ 명령1 || 명령2 ... ]

더블 파이프는 앞의 명령이 성공하면 뒤의 명령어는 실행되지 않고, 앞의 명령이 실패한다면 뒤의 명령이 실행된다.

 

 

앰퍼샌드(&) [ 명령1 & 명령2 ... ]

앰퍼샌드는 앞 명령은 일단 백그라운드 실행 상태에 놓고 뒤의 명령어를 실행한다. 더블 앰퍼샌드일때는 앞 명령의 성공/실패 여부가 뒤의 명령 실행 여부를 결정했지만 앰퍼샌드는 뒤의 명령어가 조건에 관계없이 실행된다.

뒤의 명령이 먼저 실행되므로 헷갈리지 않게 주의!

어라? echo로 foo의 값을 먼저 확인하는 것은 오케이. 그런데 foo=2를 해줬음에도 백그라운드에서 분명히 foo=2까지 보이는데 다시 foo 변수 값을 확인하니 1이 나온다. 이건 &를 사용하면 앞의 명령이 백그라운드로 가는데 그때 사용하는 쉘이 서브 쉘이어서 서브 쉘에서 foo=2가 동작하니 원래 부모 쉘에서는 foo값이 여전히 1인 것이다.

&&을 이용했으면 의도된 대로 동작했을텐데 그럼에도 &을 사용하는 이유는 굉장히 긴 시간이 걸리는 작업이면 그 동안 터미널 제어권을 뺏겨서 아무것도 못할텐데 이때 &을 사용하면 백그라운드에서 동작하되 자신은 터미널 제어권을 가져와서 다른 작업을 할 수 있게 도와주는 등의 유용한 기능을 제공해줄 수 있기 때문!!

 

파이프(|) [ 명령1 | 명령2 ... ]

파이프는 앞 명령의 결과를 뒤 명령의 입력으로 넘겨준다. 리눅스 처음 공부할 때 grep을 사용하면서 파이프는 대부분 많이 다뤄볼 것 같다.

파일 업로드 공부하면서 올렸던 칭구들. 지워야되는데

 

이와 같이 다중 명령어를 쓰는 방법으로 뒤에 자신이 원하는 명령어를 추가적으로 삽입할 수 있다.

이런 식의 공격을 말이다. 그런데 이런식의 cat /etc/passwd poc 코드는 재미가 쪼끔 없다. 그래도 시스템 종료는 해볼까??

 

음.. 아무일도 안 일어난다. 운영체제 명령어 삽입 취약점은 있으나 웹 애플리케이션의 권한이 낮아서 아무 명령이나 실행할 수 있는건 아니다. 고작 /etc/passwd를 가져온 이유도 shadow 파일은 볼 수 없기 때문이다.

정말 혹여나 웹 애플리케이션을 root 권한으로 실행할 수도 있!! 지는 않을거다. 기본적으로 허용도 안 해줌. 진짜 거의 할 이유는 없다.

 

그러면 취약점이 약해보이는데?? 아니다. 권한이 낮다고 한들 굉장히 위험한 취약점인건 분명함.

다른 시나리오에서도 했듯이 소스 코드 파일을 뒤져보면서 민감한 정보가 들어있는 DB 파일 등을 찾을 수도 있으며, 쉘에 접근했으니 악성 프로그램의 다운도 가능해지며 일부러 무한 루프를 걸거나 큰 파일을 한꺼번에 다운받는 등의 방법으로 DoS 상태를 유발할 수도 있다.

그리고 낮은 권한일지라도 다른 내부의 취약점을 이용해 강제로 권한을 상승시킬수도 있다.

 

..txt|find /usr/bin -perm -4000 -type f 2>/dev/null

페이로드가 짤려서 여기에 다시 입력함! /usr/bin에서 setuid 파일을 찾아보기 위한 명령어다. 뭐 setuid 파일은 /usr/bin 뿐 아니라 다른 곳에도 충분히 있을 수 있지만 우선 일반 사용자 권한인 만큼 한번에 찾아보긴 힘들고 하나씩 보긴 해야할 것 같다.

이런 식으로 setuid 파일을 찾아내어 setuid 설정이 잘못된 파일이나 내재된 취약점이 있는 파일을 이용하여 강제 권한 상승을 시도할 수 있다.

 

여기서 볼 파일은 pkexec 파일이다. 최신 버전 파일이라면 아무 문제가 없지만 나처럼(?) 그냥 기본 설치된 파일은 CVE-2021-4034 로컬 권한 상승 취약점이 있다. 깃허브에 취약한 pkexec를 이용하여 권한 상승 시키는 코드가 있으므로 이용한다.

 

권한이 없으니까 당연히 나오지 않지만

 

pkexec 파일 취약점을 이용해 로컬 권한을 강제로 상승시키고 shadow 파일을 cat 했더니 출력된다. 물론 tail로 뒤에 3개만 잘랐다.

하고 보니까 신기하네. 공부하면서 진짜 되는거 보면 기분 신기하고 좋고 아무튼 좋음 ㅎㅎ

 

이렇게 강력한 공격을 주통기반에서는 어떻게 보안 설정하라고 권고할까?

  • 웹 방화벽에 모든 사용자 입력 값을 대상으로 악용될 수 있는 특수문자, 특수 구문 등을 필터링 할 수 있도록 규칙 적용
  • 애플리케이션은 운영체제로부터 명령어를 직접적으로 호출하지 않도록 구현
  • 명령어를 직접 호출하는 것이 필요한 경우에는, 데이터가 OS의 명령어 해석기에 전달되기 전에 입력 값을 검증/확인하도록 구현
  • 입력 값에 대한 파라미터 데이터의 "&", "|", ";", "`" 문자에 대한 필터링 처리

일단 대부분 입력값의 검증 그리고 아예 운영체제 명령을 호출하지 않게끔 막는다.

 

  • 웹 서버 및 웹 애플리케이션 서버는 공개적으로 알려진 취약점이 제거된 상위 버전으로 업데이트해야 함
  • 클라이언트에서 전송되는 요청(Request) 값에 대한 엄격한 필터링 적용 및 OGNL (Object Graph Navigation Language) 표현식 사용을 금지하여 원격에서 임의의 명령어가 실행되지 않도록 구현해야 함

OGNL 표현식?? 이건 무지

찾아보니까 자바를 조금 더 유연하게 사용할 수 있게 도와주지만 검증 없이 사용하면 보안 이슈가 좀 있는 것 같다.