1. Webshell이란?
Webshell이란 업로드 취약점 등 을 이용하여 내부 시스템에 명령을 수행할 수 있는 코드를 말합니다. 웹이 서버에서 구동되고 있다 하여도 취약점이 존재하지 않으면, 수행되지 않으며 만약 업로드되었다 하더라도 실행 권한이 없으면, 실행이 되지 않습니다. 하지만 취약점과 실행권한이 존재할 때는 서버 내부에 명령을 수행할 수 있으므로 침해 범위가 넓어 질 수 있습니다
※ shell이란 운영체제 상에서 다양한 운영체제 기능과 서비스를 구현하고 제공하는 프로그램 입니다. 쉘은 일반적으로 CLI(Command Line Interface)와 GUI(Graphical User Interface)가 있습니다. CLI는 손으로 직접 명령어를 쳐서 수행하는 인터페이스를 가리키며 대표적으로 cmd가 있습니다. GUI는 그래픽적으로 사용자의 편의를 많이 도모하는 윈도우 Application을 예로 들 수 있습니다.
2. Webshell의 기능
Webshell이 업로드 취약점등을 이용하여 업로드 되었을 시 웹서버가 실행되는 권한과 동일한 명령어를 수행할 수 있습니다. 아래 예제에서 볼 수 있는 Webshell은 가장 간단한 종류 중 한가지로서, 사용자로부터 입력된 시스템 명령어를 쉘에 전달하는 기능을 가지고 있습니다.
위 그림은 DOS의 내부 명령어인 dir을 입력하여 디렉터리를 출력한 결과입니다. Webshell은 명령어를 직접 입력하여 결과를 얻을 수 있으며 더 나아가서는 DB에 접근하여 DB정보를 획득하거나 Iframe같은 악성 스크립트를 삽입하여 악성코드를 배포와 동시에 감염시키는 용도로 사용될 수 있습니다.
3. Webshell (dark.asp) 소개
<<dark.asp>>
이 Webshell은 인터넷 상에서 쉽게 구할 수 있는 Webshell 중 한 가지 입니다. IIS 웹서버에서 실행할 수 있는 ASP로 구현된 Webshell이며, 사용법은 아래와 같습니다.
http://192.168.137.220:8000/dark.asp?goaction=login [password : tencentisapieceofshit]
기능은 하단에서 살펴 보도록 하겠습니다.
● Serverinfo : 서버의 이름과 IP등 현재 시스템이 사용하고 있는 정보를 나타냅니다
● Object Info : 서버가 사용하고 있는 웹 컨텐츠를 나타냅니다.
ex> Wscript.shell, Adodb.stream ETC….
● User Info : 웹을 관리하고 있는 사용자 정보를 가지고 있습니다. 관리자의 로그인 정보와
패스워드 만료 날짜에 대한 정보를 볼 수 있습니다.
● C-S info : 웹서버상에 설정되어 있는 환경변수 정보 및 Webshell 접속자의 정보를 나타냅니다.
(접속자 IP, 접속자 PORT, 접속 브라우져 등)
● WS Execute : C:\Inetpub\webhack\cmd.exe -c dir 같은 값을 넣어서 명령어를 실행시킵니다.
● FSO File : 웹서버에 업로드를 하거나 웹서버에 존재하는 파일을 복사 및 수정이 가능합니다.
● App File : 웹서버에 존재하는 파일들을 수정하거나 다운로드 받을 수 있으며 상태정보를
수정할 수 있습니다.
● Ms DataBase : DataBase에 접근할 수 있으며, SQL명령을 수행할 수 있습니다.
● File Packeager : 파일을 Packing을 할 수 있으며, Unpacking을 수행 할 수 있습니다.
(Packing의 개념을 모를 경우 그냥 압축이라고 생각하시면 됩니다).
● File Searcher : 웹 디렉토리에 있는 파일을 검색할 수 있습니다.
● ServU UP : FTP를 수행하는 포트를 통해서 FTP에 접속하여 FTP기능을 사용할 수 있습니다.
● Scan Shells : Webshell기능을 수행하고 있는 페이지를 찾아서 보여줍니다.
● Some others… : 서버에서 파일을 다운로드 받거나 레지스트리 정보를 읽을 수 있습니다.
또한 포트정보를 스캐닝 할 수 있으며 웹서버에 존재하는 다른 Webshell을
디코딩 할 수 도 있습니다. 마지막 기능으로는 시스템에서 사용하는 기본 폴더
경로를 조사할 수 있습니다.
4. Webshell(dark.asp)를 이용한 Webshell 탐지
Webshell을 이용하여 현재 시스템에 업로드된 Webshell 리스트를 조사해 보았습니다. 조사내역은 아래와 같습니다.
이 Webshell을 통해서 위와 같은 파일들을 찾았습니다. 찾은 파일 내역을 살펴보면 일반적으로 사용되는 오브젝트와 메소드가 존재한다는 것을 알 수 있습니다. 대체적으로 Wscript.shell이 사용되며 Scripting.FileSystemObject도 많이 사용 됩니다. 먼저 Wscript.shell에 대해서 알아보도록 하겠습니다.
● Wscript.shell
ASP Webshell에서 자주 사용되는 오브젝트입니다 Run과 Exec메소드를 사용하여 시스템
명령어와 외부 프로그램을 실행 할 수 있습니다. 만약 상위 권한이 있을 때는 좀더 자유롭게
기능을 사용할 수있습니다.
사용방법은 아래와 같습니다
.
● Scripting.ileSystemObject
ASP Webshell은 위의 오브젝트를 사용하여 파일 조작이 가능합니다. 시스템의 권한에 따라서
파일에 읽기, 쓰기, 변경이 가능합니다.
Webshell이 사용하는 오브젝트와 메소드를 확인한 결과 일반적으로 웹페이지에서 사용하는 종류가 아니라는 것을 알 수 있습니다. 이러한 오브젝트는 시스템에서 정보를 가져오거나 시스템 파일을 실행하는 것으로 이러한 정보를 통하여 Webshell을 탐지 할 수 있습니다. Webshell을 탐지할 수 있는 패턴을 만들어서 Webshell을 차단하기 위해서는 웹방화벽을 이용하거나 IDS, IPS를 이용할 수 있으며, SNORT와 같은 침입 탐지 Application을 사용하여 탐지 및 차단이 가능합니다.
※ 위와 같은 구문은 공격자 뿐만 아니라 관리자나 사용자도 사용할 수 있는 경우도 있으므로 오탐을 할 수 있는 경우가 생기므로 주의가 필요합니다.
※ 이 문서는 서버에 설치하여 Webshell을 차단할 수 있는 Application 기준으로 작성됩니다.
5. 침임탐지Application을 이용한 Webshell 탐지 방법 - SNORT
SNORT는 오픈 소스로 개발되어 누구나 사용할 수 있는 네트워크 공격 탐지 툴입니다. 이 툴은 IDS기능과 IPS기능으로 사용 할 수 있습니다. 사용 방법은 시그너처탭을 이용하여 공격에 해당하는 문자열을 탐지하여 알리거나 차단 할 수 있습니다. SNORT의 룰을 커스터 마이징 하는 법은 아래와 같습니다. 처음 접하는 사용자들은 어려울 수 있으나 아래 예제를 통해서 알아 보도록 하겠습니다.
ex > alert tcp any any -> any 21 (msg:"Trons_IIS_FTP_EXPLOIT"; content:"|53495445204b53455859|"; offset:0; depth:50;)
1 2 3 4 5 6 7 8
표 아래에 빨간색으로 표시되어 있는 부분은 SNORT탐지룰을 작성한 것입니다. 이 룰에서 가장 중요한 부분은 8번 옵션부분입니다.
옵션 부분에 기입되는 탭은 아래와 같습니다.
● msg
로그에 저장되거나 alert가 발생될 때 msg로 지정된 텍스트가 사용됩니다.
● content
패킷에서 사용되는 문자열을 지정할 수 있습니다. 스트링 값과 바이너리를 지정할 수 있습니다.
스트링값은 " " 으로 문자열을 묶어서 지정할 수 있으며, 바이너리일 경우(16진수)에는
"|바이너리 값|"와 같이 따옴표와 파이프라인으로 묶어서 표현합니다. SNORT에서 가장 많이
사용되는 옵션이므로 아래의 예제를 참고하시기 바랍니다.
PAYLOAD는 아래의 그림을 바탕으로 설명하겠습니다.
Conetent에 삽입되는 패턴들은 패킷의Data영역에서 가져오게 됩니다. 이 Data영역을 PAYLOAD라고 말하며 바이너리와 아스키코드로 확인 할 수 있습니다.
※ Data 영역은 위 그림에서 색칠된 부분을 나타냅니다.
● offset
content옵션에서 지정한 문자열의 검색을 시작할 위치를 지정합니다.
만약 offset이 0이면 47부터 시작하며 offset이 11일 경우에는 2e부터 시작합니다.
표기법은 『 offset:0』와 같이 표기됩니다.
※ 16진수로 b는 11이며, 두 자리 수 숫자 하나는 1byte의 공간을 차지합니다.
● dsize
패킷의 PAYLOAD 사이즈를 확인하고 범위를 지정할 수 있습니다. 예를 들어 dsize:200<>300;
이라고 하면 200바이트에서 300바이트 크기의 패킷을 지정합니다..
● depth
PAYLOAD의 depth를 지정하여 패턴 매칭을 실시합니다. depth를 지정함으로서 처리에 대한
부하는 경감 될 수 있지만, 오탐 확률이 높아질 수 있으므로 주의 하시기 바랍니다.
● flags
TCP 프로토콜에 Flag를 다룹니다. 여러 Flag를 나열하고자 할 때는 『Flags:FS;』 식으로 연결지어
사용합니다. 또한 +( or) *( and) !( not)등의 파라미터도 사용가능합니다.
TCP flags (-fS/ -fA/ -fR/ -fP/ -fF/ -fU/ -fE/ -fC/ -f-)
Specify the TCP flags:
Protocol |
flags |
내용 |
tcp |
-fS |
(SYN) |
|
-fA |
(ACK) |
|
-fR |
(RST) |
|
-fP |
(PSH) |
|
-fF |
(FIN) |
|
-fU |
(URG) |
|
-fE |
(ECE) |
|
-fC |
(CWR) |
|
-f |
NONE |
● nocase
일반적으로 패턴은 대문자와 소문자를 구별합니다. Nocase를 사용하면 대소문자 구분을
무시합니다. 따라서 대소문자를 변경하여 들어오는 공격 패턴도 탐지하여 탐지율을 높일 수
있습니다.
6. 패턴 제작 및 Webshell 방어
Webshell 탐지 방법에서 살펴보았던 위의 표를 기준으로 패턴을 제작하도록 하겠습니다. 패턴은 Wscript.shell을 이용하여 작성하였습니다.
작성된 패턴은 아래와 같습니다.
alert tcp any any -> 192.168.137/24 any (msg:"webshell"; content:"WSCRIPT"; sid:2000;) |
tcp프로토콜을 사용하는 모든 아이피와 모든 포트가 192.168.137/24 대역의 모든 포트로 접근하였을 때 content에 나와 있는 패턴(WSCRIPT)를 확인하고 로그에 webshell이라는 msg를 남깁니다. 이 패턴을 수행하기 위하여 아래와 같은 snort명령어를 수행하였습니다.
snort.exe -v -c c:\Snort\rules\webshell.rules -l c:\Snort\log -P 50000 |
위 명령어는 webshell.rules라는 패턴을 기준으로 c:\Snort\log안에 로그를 생성하는 내용입니다.
SNORT명령어를 수행한 후 Webshell탐지를 수행하고 있는지 확인 하기 위하여 웹서버에 Webshell 업로드를 수행하였습니다.
업로드가 완료되자 alert이 되는 것을 확인 할 수 있으며, 지정된 로그 안에 alert된 msg가 생성됩니다. 생성된 msg는 아래와 같습니다.
[**] [1:2000:0] webshell [**]
[Priority: 0]
01/29-18:17:23.027943 192.168.137.1:11511 -> 192.168.137.220:8000
TCP TTL:128 TOS:0x0 ID:45241 IpLen:20 DgmLen:1500 DF
***A**** Seq: 0x170F6430 Ack: 0xF65AE3BC Win: 0xFFE6 TcpLen: 20 |
SNORT탐지 Rule을 만들기 위해서는 관리자가 탐지하고자 하는 Webshell에 대하여 PAYLOAD를 확인하고 확인된 PAYLOAD안에서 패턴을 조사하여 Rule들을 만들면 됩니다.
만들어진 Rule들을 만들면 IDS와 IPS기능을 갖출 수 있습니다.
SNORT의 패턴은 여려 장비에서도 비슷하게 사용이 되므로 한번 익혀두면 다른 장비에서도 유용하게 사용 할 수 있습니다.
그 외 Webshell 패턴은 아래와 같습니다.
language *= *(vbscript|jscript)\.encode |
*(\$cmd|\$pwd|\$command|\$exec|ps -aux|\$cmdline|\$Mcmd) * |
[^a-zA-Z_>.]eval(\ |\t)*\(.*_POST *\[.*\] |
[^a-zA-Z_>.]exec(\ |\t)*\( |
[^a-zA-Z_>.]proc_open(\ |\t)*\( |
[^a-zA-Z_>.]popen(\ |\t)*\(.*\$.*\) |
[^a-zA-Z_>.]shell_exec(\ |\t)*\( |
[^a-zA-Z_>.]passthru(\ |\t)*\( |
[^a-zA-Z_>.]system(\ |\t)*\( |
위의 내용을 바탕으로 Webshell 탐지 패턴을 만들어 적용하더라도 변형된 Webshell이 추가적으로 발견될 수도 있습니다. 따라서 새로운 Webshell이 확인되었을 때는 그 Webshell에 따른 패턴을 지속적으로 업데이트 하여 탐지율을 높여야 합니다.