커맨드 인젝션은 SQL 인젝션 만큼이나 위험한 취약점이다. SQL 인젝션은 일반적으로 DB의 데이터가 유출될 가능성이 높은 취약점이며 커맨드 인젝션은 서버 전체의 통제권을 해커에게 빼앗길 수도 있는 취약점이기 때문에 일반적으로 SQL인젝션보다 더 위험하다고 볼 수도 있다.
커맨드 인젝션은 웹페이지에서 이용자에게 입력받거나 별도로 생성한 정보를 서버측의 운영체제 명령어와 결합하여 실행할 때 발생할 수 있는 취약점이다.
DVWA의 Command Injection 실습 페이지에서는 다음과 같은 예를 들어준다.
DVWA 명령어 인젝션 실습 페이지 – Ping a device
IP 주소를 이용자에게 입력받아 운영체제의 Ping 명령과 조합하여 실행하고 그 결과를 화면에 보여주는 명령이다.
다음과 같이 192.168.219.52 라는 IP를 입력하면 그 결과를 적나라하게 보여준다.
DVWA – Ping 실행 결과
이런 화면을 해커가 발견하면 해커는 즉각 다음과 같이 취약점 여부를 확인하려 한다.IP 뒤에 다른 명령어를 연속으로 입력하는 형태다.
DVWA – Command Injection 테스트
192.168.219.52 다음에 ; 을 붙여주고 다음에 ifconfig -a 라는 명령을 입력했다.
그랬더니 두 명령어가 모두 실행되어 그 결과가 함께 표시된다.
당연히 해커는 IP를 입력한 뒤 출력되는 내용이 운영체제의 ping 이라는 명령어의 실행 결과라는 것을 알아챈 것이다. 즉 그 내용을 모르면 취약점이 있는지 확인하지 못했을 것이다.
다음은 운영체제의 쉘에서 ping 명령을 수행한 결과다. 위 화면의 결과와 비교해보면 완벽하게 동일하다.
Command line에서 실행한 ping 명령
실행한 시점이 다르기 때문에 응답시간의 숫자는 다를 수 있다.
다음은 ifconfig -a의 실행결과다.
명령행에서 ifconfig 명령 실행 화면
두 명령어의 실행결과가 쉘에서 실행한 것과 웹에서 실행한 것이 완벽하게 동일하다.
이쯤에서 끝난다면 그냥 취약점은 취약점으로 끝나고 말 것이다. 하지만 해커들의 상상력은 일반인들의 상상력을 초월한다. 이쯤되면 해커들은 서버에 직접 침투하고 싶어진다. 쉘스크립트도 만들고 싶어지고 C로 된 해킹 프로그램도 업로드하고 싶어지고… 하고 싶은게 정말 많을 것이다.
그렇다면 뭔가… 더 손쉽게 명령을 입력하고 작업을 할 수 있는 환경이 필요하다. 이럴 때 사용할 수 있는 해킹기범이 바로 바인드쉘이나 리버스쉘이다.
여기서는 바인드쉘을 작성해 본다.
바인드쉘은 netcat 이라는 명령을 이용해 손쉽게 서버에 생성할 수 있다. 즉 커맨드인젝션 취약점을 이용해 웹서버에 설치되어 있는 netcat 명령을 이용해 특정 TCP 포트를 Listen하게 해놓은 다음, 원격의 리눅스나 윈도PC에서 netcat 명령을 이용해 접속하는 것이다.
서버에 netcat 명령을 이용해 바인드쉘을 만드는 명령은 다음과 같다.
$ mkfifo /tmp/pipe
$ sh /tmp/pipe | nc -l 4444 > tmp/pipe
이 두 라인을 실행하면 TCP 4444 포트를 Bind하여 Listen하고 있는 바인드쉘이 만들어진다.
이 두 라인을 다음과 같이 DVWA의 Command Injection 실습 페이지에 아무 의미없는 IP와 함께 입력하고 Submit 한다.
DVWA – Command Injection 취약점을 이용한 Bind Shell 실행
입력하고 나면 이전의 명령처럼 화면이 리프레쉬되며 결과가 표시되지 않는다. 왜냐하면 바인드쉘을 만들기 위해 실행한 /bin/sh가 종료되지 않고 실행중 상태로 남아있기 때문이다.
이제 다른 리눅스 혹은 Windows PC(netcat이 설치된)에서 다음과 같이 명령을 실행한다.
DVWA – Bind Shell에 접속하기
192.168.219.60은 DVWA가 실행된 서버다. IP를 어떻게 알았냐고? 앞의 화면에서 ifconfig -a를 실행한 결과에서 DVWA가 설치된 서버의 IP를 확인할 수 있다.
그런데 nc 명령을 입력한 뒤 nc 명령이 종료되지 않고 다음라인에서 프롬프트가 대기중이다. 뭔가 입력을 기다리는 듯 하다.
다음과 같이 여러 명령어를 입력해보자.
Bind Shell에서 명령어 실행
hostname 명령을 입력하자 ubuntu18 이 출력된다.그리고 uname -a 명령을 입력하니 뭔가 긴 줄이 출력된다. who am i 명령에는 응답이 없는듯 하고 whoami 명령에는 www-data 라는 응답이 출력된다.
이쯤에서 “어~ 왜 쉘이 ID와 패스워드를 안물어보지??”라는 의구심이 들지 않는가? 왜 물어보지 않는지는 Unix 운영체제의 로그인 과정에 대해 별도로 공부해보기 바란다.
어쨌든 지금 이 상태는 DVWA 서버에서 실행된 바인드쉘을 통해 서버에 telnet 접속한 것과 같은 효과를 낸 것이다. 명령을 입력하는 대로 그 결과가 출력된다.
ifconfig -a 명령을 다시 입력해봤다.
Bind Shell에서 운영체제 명령어 실행결과
DVWA 서버의 네트워크 설정정보가 그대로 출력된다.
이쯤되면 이 서버는 해커의 놀이터로 전락했다고 볼 수 있다.