T09 · Insecure Skill Coding Practices
- Location
scripts/check_lottery.py:79- Finding
TLS Certificate and Hostname Verification Disabled
- Content
View full analysis
Vulnerability Details
File Location:
scripts/check_lottery.py, lines 79–82 and 103
Vulnerability Type: Improper TLS certificate validation
Risk Level: HighVulnerable Code
python import ssl ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE # Build the query URL params = { "gameNo": config["game_no"], "provinceId": "0", "isVerify": "1", "termLimits": "1" } query_string = "&".join([f"{k}={v}" for k, v in params.items()]) full_url = f"{config['url']}?{query_string}" req = urllib.request.Request( full_url, headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Referer": "https://www.lottery.gov.cn/", "Accept": "application/json" } ) with urllib.request.urlopen(req, timeout=15, context=ctx) as resp: data = json.loads(resp.read().decode())Technical Analysis
The code creates a default TLS context but then explicitly disables its two essential server-authentication controls:
ctx.check_hostname = Falseprevents verification that the certificate belongs towebapi.sporttery.cn.ctx.verify_mode = ssl.CERT_NONEaccepts certificates that are untrusted, expired, self-signed, or issued for another host.
Although the API URL uses HTTPS, these settings remove server identity authentication. Encryption alone does not prevent an active network attacker from terminating the connection with an arbitrary certificate and returning forged JSON.
The response is parsed and trusted without an independent authenticity check. Its draw result, prize details, pool balance, and sales amount are subsequently used to calculate and display financially relevant lottery results.
Attack Path
- A user invokes the Skill to check one or more lottery tickets.
- The script connects to the configured lottery API over a network controlled or intercepted by an attacker, such as a compromised router, malicious Wi-Fi ...[truncated 1248 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove the custom settings that disable certificate and hostname verification.
- Use Python's default verified TLS behavior:
python with urllib.request.urlopen(req, timeout=15) as resp: data = json.loads(resp.read().decode("utf-8"))Alternatively, retain an explicit default context without weakening it:
python import ssl ctx = ssl.create_default_context() with urllib.request.urlopen(req, timeout=15, context=ctx) as resp: data = json.loads(resp.read().decode("utf-8"))- Do not use
ssl.CERT_NONEor setcheck_hostnametoFalsein production. - If the runtime requires a private or unusual trust chain, install the appropriate CA certificate and load it through
ssl.create_default_context(cafile=...)rather than bypassing validation. - Validate the response schema and expected data types before using API fields. This does not replace TLS verification, but it limits malformed or unexpected data handling.
- Return a clear failure when certificate validation fails; never silently retry with an insecure SSL context.
- Add an automated test using an untrusted or hostname-mismatched certificate and verify that the request is rejected.
