[Security] No authentication on ANY endpoint — full account takeover, mass spam, private chat data exposure
WeixinBot — Multiple Critical Vulnerabilities (No Authentication on Any Endpoint)
This report documents multiple critical security vulnerabilities in the master branch of WeixinBot, all sharing a single root cause: the Flask application has zero authentication on every endpoint. There is no login, token, session, API key, or ownership check anywhere in the codebase. Any caller who can reach the HTTP port can fully control the bot's authenticated WeChat session — impersonate the owner, send arbitrary messages/files to any contact or group, enumerate contacts, and read all stored private chat histories.
Each finding was verified against the current source.
Finding 1 — [CRITICAL] Missing authentication on message-sending endpoints (account impersonation)
Location: wxbot_project_py2.7/weixin_bot.py:131-172
The message-sending routes accept a fully attacker-controlled to parameter and message content directly from the URL, with no authentication:
@app.route('/send_msg/<to>/<msg>') # 131
@app.route('/send_img/<to>/<img>') # 141
@app.route('/send_emot/<to>/<emot>') # 152
@app.route('/send_file/<to>/<file>') # 163None of these have any @login_required, token, session, or API key check. The to path parameter is a direct object reference passed straight to wechat.send_text / send_img / send_emot / send_file, and the backend sends the message as the logged-in WeChat account to any user or group ID supplied by the requester.
Impact: Anyone reachable on the HTTP port can impersonate the bot owner — sending phishing links, fraudulent payment requests, malware files, or social-engineering messages from a trusted account. The bot's authenticated WeChat session is effectively a public puppet.
Steps:
# send arbitrary text to any contact/group from the victim's WeChat:
curl "http://<host>/send_msg/filehelper/transfer%20me%20money"
curl "http://<host>/send_msg/<victim_wxid>/click%20this%20http://evil.com"Finding 2 — [CRITICAL] Unauthenticated mass messaging (spam relay) with no recipient validation
Location: wxbot_project_py2.7/weixin_bot.py:174-248
The mass-send endpoints accept a client-provided to_list array containing arbitrary recipient IDs, with no server-side validation:
@app.route('/mass_send_msg/', methods=["GET","POST"]) # 216
@app.route('/mass_send_img', methods=["GET","POST"]) # 225
@app.route('/mass_send_emot', methods=["GET","POST"]) # 234
@app.route('/mass_send_file', methods=["GET","POST"]) # 243mass_send (line 174) iterates over every ID in to_list and calls the bot's authenticated send APIs. Broken business rules: (1) no authentication — anyone triggers mass sends; (2) no recipient validation — to_list is not checked against the bot's contact list; (3) no rate limiting — only a 1-second sleep between batches of 20; (4) no idempotency — replays send duplicates.
Impact: An attacker turns the bot into an unauthenticated spam/phishing relay, broadcasting arbitrary content to thousands of arbitrary WeChat IDs from a trusted account.
Steps:
curl -X POST "http://<host>/mass_send_msg/" \
-H "Content-Type: application/json" \
-d '{"to_list":["@@group1","@@group2","wxid_user1","wxid_user2"],"msg":"Free coupons: http://scam.com"}'
# repeat hundreds of times; each request reaches all IDs in to_list.Finding 3 — [CRITICAL] Broken Access Control / IDOR exposing private chat logs and contact data
Location: wxbot_project_py2.7/weixin_bot.py:70-97
The data-access endpoints return full contact rosters, group member lists, and complete chat histories with no authentication and no ownership check:
@app.route("/group_list") # 70 -> all groups (names, IDs, member counts, owner IDs)
@app.route('/group_member_list/<g_id>') # 79 -> full member rosters (wxids, nicknames)
@app.route('/group_chat_log/<g_name>') # 89 -> entire chat history (text, media paths, links, system msgs)g_id and g_name are direct references to private WeChat rooms and chat history. Any reachable client can enumerate or query these objects.
Impact: Complete privacy breach — all the operator's private conversations, contact lists, and group memberships are publicly readable.
Steps:
# enumerate all groups:
curl "http://<host>/group_list"
# harvest member rosters:
curl "http://<host>/group_member_list/<g_id>"
# download entire private chat history:
curl "http://<host>/group_chat_log/<g_name>"Summary table
| # | Finding | Severity | Location |
|---|---|---|---|
| 1 | No auth on message-sending (impersonation) | CRITICAL | weixin_bot.py:131-172 |
| 2 | Unauthenticated mass messaging (spam relay) | CRITICAL | weixin_bot.py:174-248 |
| 3 | Unauthenticated exposure of private chat/contact data | CRITICAL | weixin_bot.py:70-97 |
All three share the same root cause: the Flask app has zero authentication markers. The fix is to add an authentication layer (API key / token) to every endpoint, validate to/to_list against the bot's own contact list, and enforce rate limiting.
This issue was found by automated security audit and verified against the current master branch source.
Source: Urinx/WeixinBot