Skip to content

Commit

Permalink
Added Ipv6 support for RPC Filters
Browse files Browse the repository at this point in the history
  • Loading branch information
sagiesec committed May 30, 2023
1 parent 29f802d commit 2b16952
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [[email protected]](mailto:[email protected])
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 [[email protected]](mailto:[email protected])

# 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.
Expand Down Expand Up @@ -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|
Expand Down
69 changes: 66 additions & 3 deletions rpcFwManager/rpcfilters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,17 @@ void disableAuditingForRPCFilters()
setLocalRPCSecurityPolicyInReg(4);
}

FWP_BYTE_ARRAY16* allocateFWPByteArray16(const BYTE* byteArray)
{
FWP_BYTE_ARRAY16* byteArrayPtr = static_cast<FWP_BYTE_ARRAY16*>(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 };
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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};
Expand All @@ -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 };
Expand Down Expand Up @@ -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())
{
Expand Down

0 comments on commit 2b16952

Please sign in to comment.