|
2 | 2 | using System.Linq; |
3 | 3 | using System.Collections.Generic; |
4 | 4 | using System; |
| 5 | +using Aikido.Zen.Core.Models.Ip; |
5 | 6 |
|
6 | 7 | namespace Aikido.Zen.Core.Helpers |
7 | 8 | { |
8 | 9 | public class IPHelper |
9 | 10 | { |
| 11 | + private static readonly IPRange _privateIpRanges; |
| 12 | + |
| 13 | + static IPHelper() |
| 14 | + { |
| 15 | + _privateIpRanges = new IPRange(); |
| 16 | + |
| 17 | + // IPv4 private ranges |
| 18 | + var ipv4Ranges = new[] |
| 19 | + { |
| 20 | + "0.0.0.0/8", |
| 21 | + "10.0.0.0/8", |
| 22 | + "100.64.0.0/10", |
| 23 | + "127.0.0.0/8", |
| 24 | + "169.254.0.0/16", |
| 25 | + "172.16.0.0/12", |
| 26 | + "192.0.0.0/24", |
| 27 | + "192.0.2.0/24", |
| 28 | + "192.31.196.0/24", |
| 29 | + "192.52.193.0/24", |
| 30 | + "192.88.99.0/24", |
| 31 | + "192.168.0.0/16", |
| 32 | + "192.175.48.0/24", |
| 33 | + "198.18.0.0/15", |
| 34 | + "198.51.100.0/24", |
| 35 | + "203.0.113.0/24", |
| 36 | + "240.0.0.0/4", |
| 37 | + "224.0.0.0/4", |
| 38 | + "255.255.255.255/32" |
| 39 | + }; |
| 40 | + |
| 41 | + // IPv6 private ranges |
| 42 | + var ipv6Ranges = new[] |
| 43 | + { |
| 44 | + "::/128", // Unspecified address |
| 45 | + "::1/128", // Loopback address |
| 46 | + "fc00::/7", // Unique local address (ULA) |
| 47 | + "fe80::/10", // Link-local address (LLA) |
| 48 | + "::ffff:127.0.0.1/128", // IPv4-mapped address |
| 49 | + "::ffff:0:0/96" // IPv4-mapped addresses |
| 50 | + }; |
| 51 | + |
| 52 | + foreach (var range in ipv4Ranges.Concat(ipv6Ranges)) |
| 53 | + { |
| 54 | + _privateIpRanges.InsertRange(range); |
| 55 | + } |
| 56 | + } |
| 57 | + |
10 | 58 | public static string Server |
11 | 59 | { |
12 | 60 | get |
@@ -141,39 +189,14 @@ private static long IMask(int s) |
141 | 189 |
|
142 | 190 | /// <summary> |
143 | 191 | /// Checks if an IP address is a private IP address. |
144 | | - /// Supports both IPv4 and IPv6 address formats. |
| 192 | + /// Supports both IPv4 and IPv6 address formats using a comprehensive list of private IP ranges. |
| 193 | + /// https://github.com/AikidoSec/firewall-node/blob/02f25f1e2566c84e695b9f4b7d1723138485654d/library/vulnerabilities/ssrf/isPrivateIP.ts |
145 | 194 | /// </summary> |
146 | 195 | /// <param name="ip">The IP address to check.</param> |
147 | 196 | /// <returns>True if the IP address is private, false otherwise.</returns> |
148 | 197 | private static bool IsPrivateIPAddress(IPAddress ip) |
149 | 198 | { |
150 | | - byte[] ipBytes = ip.GetAddressBytes(); |
151 | | - |
152 | | - // Check if IPv4 private address ranges |
153 | | - if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) |
154 | | - { |
155 | | - // 10.0.0.0/8 |
156 | | - // 172.16.0.0/12 |
157 | | - // 192.168.0.0/16 |
158 | | - if (ipBytes[0] == 10 || |
159 | | - (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) || |
160 | | - (ipBytes[0] == 192 && ipBytes[1] == 168)) |
161 | | - { |
162 | | - return true; |
163 | | - } |
164 | | - } |
165 | | - |
166 | | - // Check if IPv6 private address ranges |
167 | | - if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) |
168 | | - { |
169 | | - // Unique local addresses (fc00::/7) |
170 | | - if ((ipBytes[0] & 0xFE) == 0xFC) |
171 | | - { |
172 | | - return true; |
173 | | - } |
174 | | - } |
175 | | - |
176 | | - return false; |
| 199 | + return _privateIpRanges.IsIpInRange(ip.ToString()); |
177 | 200 | } |
178 | 201 | } |
179 | 202 | } |
0 commit comments