# [FWordCTF 2021](https://ctftime.org/event/1405) ###### tags: `ctf` {%hackmd theme-dark %} # Forensics ### `listening?` - Challenge description ![](https://i.imgur.com/v24T55T.jpg) ### Got a pcpa file (challenge.pcap) - By Wireshark, I opened the pcap file and found it was about 9 seconds record of the packets ![](https://i.imgur.com/7DMVTYj.jpg) - I mainly focused on HTTP Stream, so I filtered "http" in Wireshark and found something interesting. ![](https://i.imgur.com/EcHxJoS.jpg) - 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. ![](https://i.imgur.com/uhRP0uR.png) ### Made a google API call - Payload ```bash= 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. ```c= { "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 ```json= { "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](https://colab.research.google.com/drive/1XtNzIoqCkYQY9pzlZEYtV-PeP7IGOHz7?usp=sharing), 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. ```python= 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}` ```c= 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. ![](https://i.imgur.com/jKDNMlF.jpg) ### Categories - We solved four challenges: one Welcome, one Cryptography, one bash, and one Forensics challenge. ![](https://i.imgur.com/aXRBAM4.jpg) ![](https://i.imgur.com/apJoHwi.jpg) ### 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. ![](https://i.imgur.com/oPDP4hL.jpg) ### Score over time - ![](https://i.imgur.com/M04Gwdd.jpg) ## Resources - [Gmail API Quickstart](https://developers.google.com/gmail/api/quickstart/python) - [Read email](https://www.geeksforgeeks.org/how-to-read-emails-from-gmail-using-gmail-api-in-python/) - [Google Developers - OAuth 2.0 Playground](https://developers.google.com/oauthplayground/)