|
19 | 19 | // the connection is direct to the target (not an HTTP proxy). |
20 | 20 | $squid_socks = 'cache_peer %s parent %d 0 no-digest no-netdb-exchange connect-fail-limit=2 connect-timeout=8 round-robin no-query allow-miss proxy-only originserver name=%s %s'; |
21 | 21 |
|
| 22 | +// Reject any byte that could break squid.conf tokenization or inject |
| 23 | +// a new directive (whitespace, control chars, quotes, backslash, '#'). |
| 24 | +// Applied to host/user/pass to prevent config injection from a tainted |
| 25 | +// proxyList.txt (e.g. one fetched from a remote URL). |
| 26 | +$reject_unsafe = '/[\s"#\\\\\x00-\x1F\x7F]/'; |
| 27 | + |
22 | 28 | while ($line = fgets($proxies)){ |
23 | 29 | $line = trim($line); |
| 30 | + if ($line === '' || $line[0] === '#') { |
| 31 | + continue; |
| 32 | + } |
24 | 33 | $proxyInfo = array_combine($keys, array_pad((explode(":", $line, 5)), 5, '')); |
25 | 34 | $squid_conf = []; |
26 | 35 | $cred = ''; |
27 | 36 | if(!$proxyInfo['host'] && !$proxyInfo['port']){ |
28 | 37 | continue; |
29 | 38 | } |
30 | 39 |
|
| 40 | + // Validate host: hostname or IPv4 literal. No shell/conf metachars. |
| 41 | + // IPv6 literals are not supported: the naive explode(":") parser above |
| 42 | + // cannot split "[::1]:8080:..." correctly, so ':' / '[' / ']' are rejected |
| 43 | + // to avoid giving the impression that IPv6 is accepted. |
| 44 | + if (preg_match($reject_unsafe, $proxyInfo['host']) || |
| 45 | + !preg_match('/^[A-Za-z0-9._-]+$/', $proxyInfo['host'])) { |
| 46 | + fwrite(STDERR, "Skipping proxy with invalid host: " . rawurlencode($proxyInfo['host']) . PHP_EOL); |
| 47 | + continue; |
| 48 | + } |
| 49 | + // Validate port: 1-65535. |
| 50 | + if (!ctype_digit((string)$proxyInfo['port']) || |
| 51 | + (int)$proxyInfo['port'] < 1 || (int)$proxyInfo['port'] > 65535) { |
| 52 | + fwrite(STDERR, "Skipping proxy with invalid port: " . rawurlencode((string)$proxyInfo['port']) . PHP_EOL); |
| 53 | + continue; |
| 54 | + } |
| 55 | + // Validate credentials: no whitespace/control chars/quotes/backslash/#. |
| 56 | + // (SOCKS5 RFC1929 allows up to 255 bytes of arbitrary octets, but we |
| 57 | + // conservatively reject bytes that would break squid.conf.) |
| 58 | + if (($proxyInfo['user'] !== '' && preg_match($reject_unsafe, $proxyInfo['user'])) || |
| 59 | + ($proxyInfo['pass'] !== '' && preg_match($reject_unsafe, $proxyInfo['pass']))) { |
| 60 | + fwrite(STDERR, "Skipping proxy with unsafe characters in credentials: " . $proxyInfo['host'] . PHP_EOL); |
| 61 | + continue; |
| 62 | + } |
| 63 | + if (strlen($proxyInfo['user']) > 255 || strlen($proxyInfo['pass']) > 255) { |
| 64 | + fwrite(STDERR, "Skipping proxy with credentials exceeding 255 bytes: " . $proxyInfo['host'] . PHP_EOL); |
| 65 | + continue; |
| 66 | + } |
| 67 | + |
31 | 68 | if(!$proxyInfo['scheme']){ |
32 | 69 | //open proxy server IP:Port Pattern. |
33 | 70 | //No create gost |
|
0 commit comments