惡意腳本利用 PHP fsockopen() 建立 UDP 連接,向目標 IP 發送大量數據包:
<?php
$fp = fsockopen("udp://$targetIp", $port, $errno, $errstr, 5);
if ($fp) {
fwrite($fp, $payload); // 發送攻擊負載
fclose($fp);
}
特點:UDP 無連接、無狀態、源 IP 易偽造、帶寬放大效應明顯(如 NTP/DNS 放大攻擊)。本地用戶通過 Web Shell 或合法上傳腳本發起,消耗服務器出口帶寬,導致合法服務不可用。
; 禁用網絡套接字與命令執行相關函數
disable_functions = exec,system,passthru,shell_exec,proc_open,proc_close,proc_get_status,popen, \
fsockopen,pfsockopen,stream_socket_client,stream_socket_server,stream_socket_accept, \
stream_socket_sendto,stream_socket_recvfrom,stream_socket_get_name, \
pcntl_exec,pcntl_fork,pcntl_signal,pcntl_alarm, \
dl,openlog,syslog,readlink,symlink,link,chroot,chgrp,chown, \
ini_alter,ini_restore,putenv,getenv, \
highlight_file,show_source,phpinfo,get_cfg_var, \
disk_free_space,disk_total_space,diskfreespace
生效方式:修改後重載 PHP-FPM 或重啟 Apache/IIS。驗證:php -r "var_dump(function_exists('fsockopen'));" 應返回 bool(false)。
suhosin.executor.disable_eval = On、suhosin.executor.func.blacklist 精細控制fsockopen 等函數,上下文感知攔截(如:允許內部服務調用,禁止外網)fsockopen 內部處理器,記錄調用堆棧並阻斷適用於 Windows Server 2003/2008/2012/2016/2019,通過 netsh ipsec 策略實現內核級 UDP 封鎖。
@echo off
REM ==========================================
REM Windows IPsec 策略:封鎖所有入站/出站 UDP
REM 僅保留 DNS (UDP 53) 出站解析
REM 以管理員權限運行
REM ==========================================
REM 1. 創建策略
netsh ipsec static add policy name="Anti-UDP-Flood" description="Block UDP flood attacks from local scripts"
REM 2. 定義篩選器列表
netsh ipsec static add filterlist name="Allow-DNS-Outbound"
netsh ipsec static add filterlist name="Block-All-Other-UDP"
REM 3. 添加允許規則:本機 -> 任意 DNS (UDP 53)
netsh ipsec static add filter filterlist="Allow-DNS-Outbound" srcaddr=me dstaddr=any protocol=udp mirrored=yes dstport=53 description="Allow DNS queries"
REM 4. 添加封鎖規則:任意 -> 本機 所有 UDP (入站)
netsh ipsec static add filter filterlist="Block-All-Other-UDP" srcaddr=any dstaddr=me protocol=udp mirrored=yes description="Block inbound UDP"
REM 5. 添加封鎖規則:本機 -> 任意 所有 UDP (出站),排除 DNS
REM 注意:netsh ipsec 不支持「排除端口」,需通過「允許列表優先」機制
REM 此處封鎖所有出站 UDP,DNS 已在允許列表中,優先級更高
netsh ipsec static add filter filterlist="Block-All-Other-UDP" srcaddr=me dstaddr=any protocol=udp mirrored=yes description="Block outbound UDP except DNS"
REM 6. 定義篩選動作
netsh ipsec static add filteraction name="Permit" action=permit
netsh ipsec static add filteraction name="Block" action=block
REM 7. 創建規則綁定
netsh ipsec static add rule name="Allow-DNS" policy="Anti-UDP-Flood" filterlist="Allow-DNS-Outbound" filteraction="Permit"
netsh ipsec static add rule name="Block-UDP-In" policy="Anti-UDP-Flood" filterlist="Block-All-Other-UDP" filteraction="Block"
netsh ipsec static add rule name="Block-UDP-Out" policy="Anti-UDP-Flood" filterlist="Block-All-Other-UDP" filteraction="Block"
REM 8. 激活策略
netsh ipsec static set policy name="Anti-UDP-Flood" assign=y
echo 策略已激活。查看狀態:netsh ipsec static show policy name="Anti-UDP-Flood"
pause
REM 查看策略狀態
netsh ipsec static show policy name="Anti-UDP-Flood"
REM 查看篩選器
netsh ipsec static show filterlist
REM 刪除策略(恢復網絡)
netsh ipsec static delete policy name="Anti-UDP-Flood"
REM 導出策略備份
netsh ipsec static exportpolicy file=ipsec_policy_backup.reg
# 1. 允許本地回環
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# 2. 允許已建立/相關連接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 3. 允許 DNS 查詢 (UDP 53) - 僅授權 DNS 服務器
iptables -A OUTPUT -p udp -d 8.8.8.8,114.114.114.114 --dport 53 -j ACCEPT
iptables -A INPUT -p udp -s 8.8.8.8,114.114.114.114 --sport 53 -j ACCEPT
# 4. 允許 NTP 時間同步 (UDP 123) - 如有需要
# iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
# 5. 封鎖其他所有 UDP
iptables -A INPUT -p udp -j DROP
iptables -A OUTPUT -p udp -j DROP
# 6. 保存規則
iptables-save > /etc/iptables/rules.v4
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iifname "lo" accept
ct state established,related accept
ip saddr { 8.8.8.8, 114.114.114.114 } udp sport 53 accept
# 其他 UDP 隱式丟棄
}
chain output {
type filter hook output priority 0; policy drop;
oifname "lo" accept
ct state established,related accept
ip daddr { 8.8.8.8, 114.114.114.114 } udp dport 53 accept
# 其他 UDP 隱式丟棄
}
}
# 危險函數掃描腳本
grep -rn "fsockopen\|pfsockopen\|stream_socket_client\|stream_socket_server" /var/www/html --include="*.php" | grep -v ".git" | grep -v "vendor"
socket()、sendto() 系統調用,記錄進程 PID、用戶、目標 IPevt.type=sendto and evt.arg.proto=17 (UDP) 告警node_network_receive_bytes_total、node_network_transmit_bytes_total 異常激增--network=none 或自定義橋接網絡 + iptables 限制NetworkPolicy 僅允許 Pod 訪問 kube-dns (UDP 53) 和必要服務
纵深防禦:代碼層禁用 → 系統層封鎖 → 運行時監控 → 基礎設施層隔離
| 層級 | 驗證命令 | 預期結果 |
|---|---|---|
| PHP | php -r "var_dump(@fsockopen('udp://8.8.8.8',53));" | bool(false) + 警告 |
| Windows | netsh ipsec static show policy | 策略 "Anti-UDP-Flood" 狀態 Assigned: Yes |
| Linux | iptables -L -n -v | grep udp | 顯示 DROP 規則計數器增長 |
| 網絡 | 從服務器 nc -u -v -w2 8.8.8.8 53 | DNS 查詢成功 |
| 網絡 | 從服務器 nc -u -v -w2 1.1.1.1 12345 | 連接超時/被拒 |
針對本地 fsockopen UDP 洪水攻擊,單一防禦措施均可被繞過。必須構建纵深防禦體系:
disable_functions 徹底禁用套接字函數,配合 RASP 運行時攔截定期進行紅隊演練驗證防禦有效性,將攻擊面壓縮至業務絕對必要最小集。