Tencent (TSRC) — XSS Phase 2: Controlled Verification

Target program: Tencent Security Response Center (TSRC)

Scope: jiazhang.qq.com, *.exmail.qq.com (candidates from Phase 1)

Phase: 2 — approved, minimal-touch verification.

Date: 2026-11-02 (UTC)

---

0. Rules of engagement observed

Per operator approval: read-only GET requests only, no payloads, own accounts

only (several checks needed no session at all), one vulnerability per future

report, nothing that could affect Tencent users. No POST, no crafted payload, no

state change was sent. All commands logged (UTC + exit code) to

tencent/logs/phase1_commands.log; artifacts + MD5s recorded below.

---

Candidate A — jiazhang `location.search` → `index-m.html` / `index-ie.html`

Verdict: DEAD END (no reflection, no sink).

Static analysis (first, before touching the live site)

The redirect chain is a client-side UA gate, not a parameter handler:

location.search is only string-appended to a fixed relative path. It is never

split, never parsed, and never written to any DOM sink.

Query-parser census across every first-party script these pages load:

File`location.search``URLSearchParams``getUrlParam``parseUrlQuery`
`js/index.js`, `js/index-m.js`, `js/index-ie.js`0000
`js/animate.js`, `js/animate-m.js`0000
`js/swiper.js` / `js/swiper-ie.js`000**defined, 0 call sites**
`js/beacon_web.js`search used for a pixel, no DOM sink

js/swiper-ie.js @char 12561 defines a parseUrlQuery() helper (with

decodeURIComponent), but it is never invoked in that bundle (only the

definition matches). It is a dead utility inherited from Swiper, not an app path.

Live read-only verification (minimal touch, no payload)

One benign marker per page:

RequestStatusBytesMarker hits
`GET /index.html?m=p2mark7a1c9x` (iPhone UA)20060,264**0**
`GET /index-m.html?m=p2mark7a1c9x`20067,940**0**
`GET /index-ie.html?m=p2mark7a1c9x`20058,659**0**

Byte counts are identical to the Phase-1 no-query mirrors and the ETag is

unchanged (index.html "85d17dccf033d3336ba37687c94d97c4", index-m.html

"26ee3b3f8c391d7b5ce82589d65c51ac", index-ie.html

"28d1826c621b26a1db57674ddfc5ebe6"). Pages are served by tencent-cos (static

object storage); the query string is not reflected.

Conclusion: no reflection → no DOM-XSS. The redirect keeps the query string in

the URL bar, but nothing consumes it. Closed.

---

Candidate B — exmail `/qy_mng_logic/wwhelp` → `hot_log_html`

**Verdict: DEAD END for the request route. hot_log_html is server-authored, not

user-controllable from the request.** (No payload was sent.)

Static analysis of the AJAX construction

static/exmail.qq.com/js/index74e89a.js @L1 (@char 1746):


$.ajax({
  url: (o.isWwHost() ? "/mail" : "") + "/qy_mng_logic/wwhelp",
  dataType: "json",
  success: function (n) {
    n.data && n.data.hot_log_html && $(".index_hot_wrap").html(n.data.hot_log_html)
  }
})

Enumerated parameters of the request: none. The call sends no data object and

no query string — the URL is a constant chosen only by

isWwHost(){return "work.weixin.qq.com" == location.host}. No user-controllable

value is fed into the request, so there is no request→response echo surface for an

unauthenticated user.

Cross-check: no other code path calls wwhelp (grep -o 'wwhelp' in

pkg74e89b.js = 0 hits) — the endpoint contract is inert.

Read-only endpoint check (no payload, GET only)

GET https://cnc.exmail.qq.com/qy_mng_logic/wwhelp (no query string, no cookie)

returns 200, application/json, 2,019 bytes, unauthenticated:


{"data":{"hot_log_html":"<div class=\"index_hot_box\">…<li><a target=\"_blank\"
 href=\"https://work.weixin.qq.com/help?person_id=1&doc_id=669&helpType=exmail\">…

The sink is real (server returns HTML that the page injects via .html()), but the

HTML is a static "热门问题" list of Tencent help links authored server-side.

Server-side influence surface trace (from the request alone): eight benign

query parameters were sent (no payload), each returning a body byte-identical

to the baseline (md5 151f6256b1982716f4f65dacbca39923):

?lang=en, ?type=1, ?n=1, ?helpType=exmail, ?_=123, ?person_id=2,

?doc_id=669, ?callback=cb → all 200 / 2,019 B / same md5.

The endpoint ignores request parameters entirely; hot_log_html is not derived

from the request. For it to be attacker-controlled it would have to change through

an authenticated authoring route that does not exist in the mirrored code — i.e. a

hypothetical *second-order stored* injection in Tencent's own help-content system.

That is not reportable without evidence of that authoring surface, and no further

request-based test is warranted.

Proposed (NOT executed) minimal payload test plan — for the record

If the operator still wants to spend a request on it:

  1. GET /qy_mng_logic/wwhelp?<candidate-param>=p2marker for any help/language/type

selector, and diff the body md5 against baseline.

  1. Only if the body changes, check whether the changed bytes fall inside

hot_log_html; only then design an HTML-context test.

  1. Never send a <script>/handler payload unless step 2 shows a reflection.

Given the flat-response evidence, step 1 is expected to be negative and low-value;

I recommend not proceeding.

---

Honest outcome & what remains

Both approved candidates dead-end. No exploitable DOM-XSS was confirmed; no

reportable finding comes out of Phase 2.

for the request route.

Remaining leads, ranked (all require explicit operator approval before any test):

  1. exmail hot_log_html authoring surface — only if a legitimate authenticated

content-management path for the help list is identified; otherwise drop.

  1. app.mail.qq.com/list/readtemplate — static/app.mail.qq.com/js/app_landing-web.js

getPageRoute() reads ?name= and decodeURIComponents it, but only builds a

telemetry route string (no DOM sink). Would need the actual auth-gated

/list/readtemplate page to test a real sink.

  1. jQuery 1.10/1.11 gadget surface — still no first-party $.getScript/JSONP

caller with user input; only re-open if a new module appears.

  1. *.exmail.qq.com authenticated pages (own test account) — the

unauthenticated surface is exhausted.

---

Evidence index (Phase 2)

ArtifactPathMD5
wwhelp response headers`tencent/evidence/phase2/wwhelp.headers``4a686d969be0474808b210fe4895d26b`
wwhelp baseline JSON`tencent/evidence/phase2/wwhelp.json``151f6256b1982716f4f65dacbca39923`
wwhelp param-probe JSON`tencent/evidence/phase2/wwhelp_param_probe.json``151f6256b1982716f4f65dacbca39923`
jiazhang `index-ie.js` mirror`tencent/static/jiazhang.qq.com/js/index-ie.js``63f5fb22a605dff831380051008ab5fd`
jiazhang `index-m.js` mirror`tencent/static/jiazhang.qq.com/js/index-m.js``ca800505e775e3448969111d35c574ba`
jiazhang `swiper-ie.js` mirror`tencent/static/jiazhang.qq.com/js/swiper-ie.js``7d41109cf6d66985d377e6de91e05496`
jiazhang `animate-m.js` mirror`tencent/static/jiazhang.qq.com/js/animate-m.js``c25e65097337c5bcbe12ce3b2b36dd5c`
Command log`tencent/logs/phase1_commands.log`—