روشهایی برای جلوگیری از حملات SSRF در داتنت
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۲/۲۸ ۰۹:۲۸
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
IP "0.0.0.0" بود که اخیراً در مرورگرها کشف شد. این آدرس IP، اگرچه بهظاهر بیضرر به نظر میرسد، در سیستمهای لینوکس به ماشین محلی اشاره میکند و میتواند برای دور زدن محدودیتهای امنیتی مورد استفاده قرار گیرد. این موضوع نشاندهنده اهمیت اعتبارسنجی دقیق آدرسهای IP و نامهای میزبان (hostname) در برنامههای داتنت است.SsrfValidator است که وظیفه بررسی ایمنی URLهای ارائهشده توسط کاربر را بر عهده دارد.SsrfValidator شامل متدهایی است که بررسیهای مختلفی را روی URL انجام میدهند. متد اصلی، IsSafeUri، بررسی میکند که آیا URL مطلق (absolute) است، از پروتکلهای مجاز استفاده میکند و به آدرسهای داخلی اشاره نمیکند. ساختار این کد به شرح زیر است:public static class SsrfValidator
{
private static readonly string[] AllowedSchemes = new[] { "http", "https" };
public static bool IsSafeUri(Uri uri)
{
if (uri == null)
throw new ArgumentNullException(nameof(uri));
return uri.IsAbsoluteUri &&
HasValidScheme(uri) &&
IsValidHostname(uri);
}
private static bool HasValidScheme(Uri uri)
{
return AllowedSchemes.Any(x => x.Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase));
}
private static bool IsValidHostname(Uri uri)
{
var hostName = uri.DnsSafeHost;
if (IPAddress.TryParse(hostName, out IPAddress ipAddress))
{
return IsValidIpAddress(ipAddress);
}
var resolvedIpAddresses = GetIpAddressFromHostName(hostName);
return HasValidIpAddress(resolvedIpAddresses);
}
private static bool HasValidIpAddress(params IPAddress[] ipAddresses)
{
return ipAddresses.Length != 0 && ipAddresses.All(IsValidIpAddress);
}
private static bool IsValidIpAddress(IPAddress ipAddress)
{
return !ipAddress.IsPrivate();
}
private static IPAddress[] GetIpAddressFromHostName(string hostName)
{
try
{
return Dns.GetHostEntry(hostName).AddressList;
}
catch (SocketException)
{
return Array.Empty<IPAddress>();
}
}
}IsPrivate در افزونه IPAddressExtensions استفاده میشود.IPAddressExtensions شامل متدی به نام IsPrivate است که بررسی میکند آیا یک آدرس IP در محدودههای خصوصی قرار دارد یا خیر. این محدودهها شامل آدرسهای لوکالهاست، آدرسهای لینک محلی (link-local)، و کلاسهای A، B و C در IPv4، و همچنین آدرسهای محلی در IPv6 هستند. کد این افزونه به شرح زیر است:public static class IPAddressExtensions
{
public static bool IsPrivate(this IPAddress ip)
{
if (ip.IsIPv4MappedToIPv6)
ip = ip.MapToIPv4();
if (IPAddress.IsLoopback(ip))
return true;
if (ip.Equals(IPAddress.Any))
return true;
if (ip.AddressFamily == AddressFamily.InterNetwork)
return IsPrivateIPv4(ip.GetAddressBytes());
if (ip.AddressFamily == AddressFamily.InterNetworkV6)
return ip.IsIPv6LinkLocal ||
ip.IsIPv6UniqueLocal ||
ip.IsIPv6SiteLocal;
throw new NotSupportedException(
$"IP address family {ip.AddressFamily} is not supported, expected only IPv4 (InterNetwork) or IPv6 (InterNetworkV6).");
}
private static bool IsPrivateIPv4(byte[] ipv4Bytes)
{
bool IsLinkLocal() => ipv4Bytes[0] == 169 && ipv4Bytes[1] == 254;
bool IsClassA() => ipv4Bytes[0] == 10;
bool IsClassB() => ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31;
bool IsClassC() => ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168;
return IsLinkLocal() || IsClassA() || IsClassC() || IsClassB();
}
}SsrfValidator و IPAddressExtensions، به برنامهنویسان کمک میکند تا درخواستهای غیرمجاز را شناسایی و مسدود کنند. با رعایت اصول امنیتی و بهکارگیری روشهای پیشرفته مانند لیستهای سفید و بررسیهای DNS، میتوان امنیت برنامهها را بهطور قابلتوجهی ارتقا داد. توسعهدهندگان باید همیشه بهروزرسانیهای امنیتی را دنبال کنند و از منابع معتبر برای بهبود دانش خود استفاده کنند.