owned this note
owned this note
Published
Linked with GitHub
# [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/)