From 2b16952bc07dd2d2c363f642084e3f1202ea7e84 Mon Sep 17 00:00:00 2001 From: sagiezero <61778471+sagiezero@users.noreply.github.com> Date: Tue, 30 May 2023 19:34:26 +0100 Subject: [PATCH] Added Ipv6 support for RPC Filters --- README.md | 5 +-- rpcFwManager/rpcfilters.cpp | 69 +++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a643407..bf53572 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ # I Need More Information Check out our [RPC Firewall](https://zeronetworks.com/blog/stopping_lateral_movement_via_the_rpc_firewall/) blog post or our [BlackHat talk](https://www.youtube.com/watch?v=hz_YPIMeBMI) to gain better understanding of RPC, RPC attacks and the solution: the RPC Firewall. -For any questions, issues, or simlpy to shout out - we would love to hear from you! Contact us at [support@zeronetworks.com](mailto:support@zeronetworks.com) +Join our [|Zero| Labs](https://join.slack.com/t/minus273celsius/shared_invite/zt-1ulg46s8x-N0P9sEzmv3SbYTlDXVSf2g) Slack Community workspace for any questions, issues, or simlpy to shout out. +We would love to hear from you also via email (if you are that type of person). Contact us at [support@zeronetworks.com](mailto:support@zeronetworks.com) # Get Started The following tutorial shows basic installation and setup of the RPC Firewall, as well as a demo of how it protects against various RPC based attacks. @@ -136,7 +137,7 @@ This file uses the following configuration options: |opnum:| Match a RPC opnum | RPC Firewall| |verbose:| Can be either **true** or *false*. When true, outputs debug informaiton for specific RPC calls (default false)| RPC Firewall| |prot:| Matches the used protocol to any of the [protocol sequence constants](https://docs.microsoft.com/en-us/windows/win32/rpc/protocol-sequence-constants)| both RPC Firewall and Filters| -|addr:| Match a remote IP address | RPC Firewall and partially by RPC Filters, [read more here](#using-rpc-firewall-or-rpc-filters)| +|addr:| Match a remote IP address (IPv4 or IPv6)| RPC Firewall and partially by RPC Filters, [read more here](#using-rpc-firewall-or-rpc-filters)| |uuid:| Match a specific uuid | both RPC Firewall and Filters| |action:| Can be either **allow** or **block** (default allow)| both RPC Firewall and Filters| |audit:| Can be either **true** or *false*. Controls whether events are written to the *RPCFW* log (default false)| both RPC Firewall and Filters| diff --git a/rpcFwManager/rpcfilters.cpp b/rpcFwManager/rpcfilters.cpp index 67f149e..ec4f0c1 100644 --- a/rpcFwManager/rpcfilters.cpp +++ b/rpcFwManager/rpcfilters.cpp @@ -330,6 +330,17 @@ void disableAuditingForRPCFilters() setLocalRPCSecurityPolicyInReg(4); } +FWP_BYTE_ARRAY16* allocateFWPByteArray16(const BYTE* byteArray) +{ + FWP_BYTE_ARRAY16* byteArrayPtr = static_cast(malloc(sizeof(FWP_BYTE_ARRAY16))); + if (byteArrayPtr) + { + memcpy(byteArrayPtr->byteArray16, byteArray, sizeof(byteArrayPtr->byteArray16)); + } + + return byteArrayPtr; +} + FWPM_FILTER_CONDITION0 createSDCondition(const std::wstring& sidString) { FWPM_FILTER_CONDITION0 sidCondition = { 0 }; @@ -373,10 +384,12 @@ FWPM_FILTER_CONDITION0 createUUIDCondition(std::wstring& uuidString) _tprintf(_T("Failed to convert UUID:%s from string: %d\n"), uuidString,ret); } + FWP_BYTE_ARRAY16* allocatedBA16 = allocateFWPByteArray16((BYTE*) & interfaceUUID); + uuidCondition.matchType = FWP_MATCH_EQUAL; uuidCondition.fieldKey = FWPM_CONDITION_RPC_IF_UUID; uuidCondition.conditionValue.type = FWP_BYTE_ARRAY16_TYPE; - uuidCondition.conditionValue.byteArray16 = (FWP_BYTE_ARRAY16*)&interfaceUUID; + uuidCondition.conditionValue.byteArray16 = allocatedBA16; return uuidCondition; } @@ -420,6 +433,26 @@ FWPM_FILTER_CONDITION0 createProtocolCondition(std::wstring& protocol) return protoclCondition; } +bool isIpv4Addr(std::wstring& testIp) +{ + UINT32 ipv4; + + if (InetPton(AF_INET, testIp.c_str(), &ipv4) <= 0) return false; + + return true; +} + +bool isIpv6Address(const std::wstring& testIp) +{ + FWPM_FILTER_CONDITION0 ipv6Condition = { 0 }; + BYTE ipv6[16]; + + if (InetPton(AF_INET6, testIp.c_str(), &ipv6) <= 0) return false; + + return true; + +} + FWPM_FILTER_CONDITION0 createIPv4Condition(std::wstring &remoteIP) { FWPM_FILTER_CONDITION0 ipv4Condition = {0}; @@ -435,6 +468,23 @@ FWPM_FILTER_CONDITION0 createIPv4Condition(std::wstring &remoteIP) return ipv4Condition; } +FWPM_FILTER_CONDITION0 createIPv6Condition(const std::wstring& remoteIP) +{ + FWPM_FILTER_CONDITION0 ipv6Condition = { 0 }; + FWP_BYTE_ARRAY16 fwpBA16; + + InetPton(AF_INET6, remoteIP.c_str(), &(fwpBA16.byteArray16)); + + FWP_BYTE_ARRAY16* allocatedBA16 = allocateFWPByteArray16(fwpBA16.byteArray16); + + ipv6Condition.matchType = FWP_MATCH_EQUAL; + ipv6Condition.fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS_V6; + ipv6Condition.conditionValue.type = FWP_BYTE_ARRAY16_TYPE; + ipv6Condition.conditionValue.byteArray16 = allocatedBA16; + + return ipv6Condition; +} + FWPM_FILTER_CONDITION0 createEffectivelyAnyCondition() { FWPM_FILTER_CONDITION0 uuidCondition = { 0 }; @@ -484,8 +534,21 @@ void createRPCFilterFromConfigLine( LineConfig confLine, std::wstring &filterNam if (confLine.source_addr.has_value()) { - existsSourceAddr = true; - conditions.push_back(createIPv4Condition(confLine.source_addr.value())); + if (isIpv4Addr(confLine.source_addr.value())) + { + existsSourceAddr = true; + conditions.push_back(createIPv4Condition(confLine.source_addr.value())); + } + else if (isIpv6Address(confLine.source_addr.value())) + { + existsSourceAddr = true; + conditions.push_back(createIPv6Condition(confLine.source_addr.value())); + } + else + { + _tprintf(_T("Malformed address: %s\n"), confLine.source_addr); + } + } if (confLine.uuid.has_value()) {