T09 · Insecure Skill Coding Practices
- Location
wechat2md.py:22- Finding
Arbitrary URL Fetch Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
wechat2md.py:22-30andwechat2md.py:136-143
Vulnerability Type: Server-Side Request Forgery (SSRF) caused by ineffective URL validation
Risk Level: HighVulnerable Code
python def fetch_article(url: str) -> str: """抓取微信公众号文章 HTML""" headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/120.0.0.0 Safari/537.36' } response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() response.encoding = 'utf-8' return response.textpython # 验证 URL if 'mp.weixin.qq.com' not in args.url: print('警告: 这可能不是微信公众号文章链接') print(f'正在抓取文章...') try: # 抓取文章 html = fetch_article(args.url)Technical Analysis
The skill accepts a user-controlled URL and passes it directly to
requests.get(). The purported validation only checks whether the stringmp.weixin.qq.comoccurs anywhere in the URL. If it does not occur, execution is not rejected; the program merely prints a warning and still sends the request.This does not enforce the intended destination. An attacker can directly provide an unrelated URL, or place the expected text in a URL component that does not determine the destination host. For example, it could appear in user-information, a path, or a query string while the request is sent to an attacker-selected host.
In addition,
requests.get()follows HTTP redirects by default. Even if an exact initial host check were added without redirect validation, an approved URL could redirect the client to localhost, a private network address, or a cloud metadata service.Attack Path
- An attacker supplies a URL targeting an internal service, localhost, cloud metadata address, or attacker-controlled redirect endpoint.
...[truncated 1199 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the URL with
urllib.parse.urlparse()and reject it unless:- The scheme is exactly
https. - The normalized hostname is exactly
mp.weixin.qq.com, or belongs to a narrowly documented allowlist. - The URL contains no unexpected user-information or malformed authority component.
- The scheme is exactly
- Resolve the hostname before connecting and reject every loopback, private, link-local, multicast, reserved, or unspecified IPv4 and IPv6 address.
- Disable automatic redirects with
allow_redirects=False, or validate the hostname and resolved address of every redirect target before following it. - Repeat address validation immediately before connection to reduce DNS rebinding risk.
- Enforce outbound network restrictions at the container or host level so the process cannot access internal networks or metadata endpoints.
- Treat validation failures as fatal errors rather than warnings.
- Consider limiting accepted WeChat URL paths and query parameters to the minimum forms required by the skill.
- Parse the URL with
