atx0mg's Fortress.

FWordCTF 2021

Word count: 1kReading time: 6 min
2021/08/28

Forensics

listening?

  • Challenge description

Read More →

Got a pcpa file (challenge.pcap)

  • By Wireshark, I opened the pcap file and found it was about 9 seconds record of the packets

  • I mainly focused on HTTP Stream, so I filtered “http” in Wireshark and found something interesting.

  • Because of the form items I observed (shown as the image below), It made a POST request to oauth2.googleapis.com/token. I guessed it made a API call before, so I recreated the payload from the pcap, and tried to make the same API call again.

Made a google API call

  • Payload

    1
    curl -X POST https://oauth2.googleapis.com/token -d "client_secret=AER8VvrXuFfYfqjhidcekAM0&grant_type=refresh_token&refresh_token=1//044y6gZR87Kl0CgYIARAAGAQSNwF-L9IrkAFpIJPMhiGY0OPJpo5RiA5_7R-mHH-kuHwCMUeFL2JqxevGr23oBJmaxdnrD52t3X4&client_id=1097638694557-3v745luessc34bkoiqkf8tndqgvbqjpm.apps.googleusercontent.com"
  • Got an access token json. Besides, I found this access token was for reading gmail’s messages only.

    1
    2
    3
    4
    5
    6
    {
    "access_token": "ya29.a0ARrdaM9yn8BOV1WE517K_qMViaktMBVtkz3y19-hdqllimqBrXhgXmyhpPDFzAq8N42YBLjuwCLebbj78RWZCL02Pve_gfEabr_e5FFDo1BoXrNWgHj5dVIAn-lglixXue6XFc9nWsO4zRcJTTKxm39SkxxVFw",
    "expires_in": 3599,
    "scope": "https://www.googleapis.com/auth/gmail.readonly",
    "token_type": "Bearer"
    }
  • Created token.json to store credentials

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    "client_secret": "AER8VvrXuFfYfqjhidcekAM0",
    "grant_type": "refresh_token",
    "refresh_token": "1//044y6gZR87Kl0CgYIARAAGAQSNwF-L9IrkAFpIJPMhiGY0OPJpo5RiA5_7R-mHH-kuHwCMUeFL2JqxevGr23oBJmaxdnrD52t3X4",
    "client_id": "1097638694557-3v745luessc34bkoiqkf8tndqgvbqjpm.apps.googleusercontent.com",
    "access_token": "ya29.a0ARrdaM9yn8BOV1WE517K_qMViaktMBVtkz3y19-hdqllimqBrXhgXmyhpPDFzAq8N42YBLjuwCLebbj78RWZCL02Pve_gfEabr_e5FFDo1BoXrNWgHj5dVIAn-lglixXue6XFc9nWsO4zRcJTTKxm39SkxxVFw",
    "expires_in": 3599,
    "scope": "https://www.googleapis.com/auth/gmail.readonly",
    "token_type": "Bearer"
    }

    Interactive with Google gmail API

  • I run the Python script on colab, the script is shown as following block.

  • It simply provided the credentials to google authentication api’s to get the privilege to read someone’s gmail messages.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    from __future__ import print_function
    import os.path
    from googleapiclient.discovery import build
    from google_auth_oauthlib.flow import InstalledAppFlow
    from google.auth.transport.requests import Request
    from google.oauth2.credentials import Credentials
    import os.path
    import base64
    import email
    from bs4 import BeautifulSoup

    # If modifying these scopes, delete the file token.json.
    SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']

    def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
    creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
    creds.refresh(Request())
    else:
    flow = InstalledAppFlow.from_client_secrets_file(
    'credentials.json', SCOPES)
    creds = flow.run_local_server(port=0)
    # Save the credentials for the next run
    with open('token.json', 'w') as token:
    token.write(creds.to_json())

    service = build('gmail', 'v1', credentials=creds)

    # Call the Gmail API

    result = service.users().messages().list(userId='me').execute()

    # We can also pass maxResults to get any number of emails. Like this:
    # result = service.users().messages().list(maxResults=200, userId='me').execute()
    messages = result.get('messages')

    # messages is a list of dictionaries where each dictionary contains a message id.

    # iterate through all the messages
    for msg in messages:
    # Get the message from its id
    txt = service.users().messages().get(userId='me', id=msg['id']).execute()

    # Use try-except to avoid any Errors
    try:
    # Get value of 'payload' from dictionary 'txt'
    payload = txt['payload']
    headers = payload['headers']

    # Look for Subject and Sender Email in the headers
    for d in headers:
    if d['name'] == 'Subject':
    subject = d['value']
    if d['name'] == 'From':
    sender = d['value']

    # The Body of the message is in Encrypted format. So, we have to decode it.
    # Get the data and decode it with base 64 decoder.
    parts = payload.get('parts')[0]
    data = parts['body']['data']
    data = data.replace("-","+").replace("_","/")
    decoded_data = base64.b64decode(data)

    # Now, the data obtained is in lxml. So, we will parse
    # it with BeautifulSoup library
    soup = BeautifulSoup(decoded_data , "lxml")
    body = soup.body()

    # Printing the subject, sender's email and message
    print("Subject: ", subject)
    print("From: ", sender)
    print("Message: ", body)
    print('\n')
    except:
    pass
    if __name__ == '__main__':
    main()

    Results

  • Dump all the mail message (There are about 4000 lines of messages, so I filtered some of them, shown as section below)
    From the message below, we can obtain the flag:
    FwordCTF{email_forensics_is_interesting_73489nn7n4891}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Subject:  fwordplayground@gmail.com
    From: Anonymousemail <noreply@anonymousemail.me>
    Message: [<p>fwordplayground@gmail.com fwordplayground@gmail.com fwordplayground@gmail.com fwordplayground@gmail.com fwordplayground@gmail.com
    </p>]


    Subject: fwordplayground@gmail.com
    From: Anonymousemail <noreply@anonymousemail.me>
    Message: [<p>Hello everyone
    </p>]


    Subject: 1
    From: Anonymousemail <noreply@anonymousemail.me>
    Message: [<p>Hello everyone, Thank you for playing Fword CTF
    </p>]


    Subject: Flag
    From: Fword Team <fword.team@gmail.com>
    Message: [<p>FwordCTF{email_forensics_is_interesting_73489nn7n4891}
    </p>]


    Subject: Finish setting up your new Google Account
    From: Google Community Team <googlecommunityteam-noreply@google.com>
    Message: [<p>Let's get started,

    Welcome to Google. Your new account comes with access to Google products,
    apps, and services.

    Here are a few tips to get you started.

CTF results

Place and points

  • We registerd as the ToInfinityAndBeYANd, and got 1356 points resulted in 98 th in the ctf.

    Categories

  • We solved four challenges: one Welcome, one Cryptography, one bash, and one Forensics challenge.

Members - I am @x0mg

  • I solved the Froensics challenge, although I put a lot of time in osint and reverse engineering but had no good outcome.

    Score over time

Resources

Author:atx0mg

Link:https://jeff14994.github.io/2021/08/28/FWordCTF-2021/

Publish date:August 28th 2021, 5:42:17 pm

Update date:April 22nd 2022, 5:23:18 am

License:This article is licensed under CC BY-NC 4.0

CATALOG
  1. 1. Forensics
    1. 1.0.1. listening?
    2. 1.0.2. Got a pcpa file (challenge.pcap)
    3. 1.0.3. Made a google API call
    4. 1.0.4. Interactive with Google gmail API
    5. 1.0.5. Results
  2. 1.1. CTF results
    1. 1.1.1. Place and points
    2. 1.1.2. Categories
    3. 1.1.3. Members - I am @x0mg
    4. 1.1.4. Score over time
  3. 1.2. Resources