Certipy, AD CS, and the Day Suricata Told Me “dce” Isn’t a Protocol

Yeah so AD CS abuse is one of those things that looks clean in a conference talk and messy the second you try to detect it on a real sensor. I stood up Certipy in a lab, watched a pile of certificate noise hit the wire, then spent way too long arguing with Suricata about whether DCERPC is even allowed to exist as a protocol keyword.

This is that writeup. Lab notes. Not “here is the one rule that solves ESC1 forever.”

Lab shape

What I used (roughly):

  • Domain with AD CS installed (don’t half-install this — you want a real enterprise CA path)
  • Kali with Certipy
  • Packet capture while enumerating templates and requesting certs
  • Suricata in the mix for “can I write a rule that fires on this PCAP”

Basic Certipy flow once you’re on Kali:

su -
git clone https://github.com/ly4k/Certipy.git
cd Certipy
# install deps however you usually do it for that version

# find templates / misconfigs with lab admin (lab only)
certipy find -u 'Administrator@lab.local' -p '***' -dc-ip 10.0.0.10

# request / auth path depends on what you found (ESC1-style stuff, etc.)
# end state people care about: .pfx in hand, then hash / TGT abuse

There’s a solid walkthrough vibe on YouTube if you want visuals — I had this one in my notes: Certipy demo. Use it as a map, not as a substitute for reading what your CA is actually allowing.

Auditing: GPO alone is not enough

This is the part that bites people.

You can think you “turned on AD CS auditing” in Group Policy and still get almost nothing useful, because the Certification Authority itself has its own auditing checkboxes — and by default a lot of that is off.

On the CA:

  1. Open Certification Authority
  2. Right-click the CA → Properties → Auditing
  3. Turn the relevant success/failure categories on — yes, including the ones that feel noisy

If those are unchecked, don’t be shocked when your “we would have seen cert abuse” story falls apart in a postmortem.

Host-side, you’re hunting certificate services events / request patterns and weird enrollments from accounts that shouldn’t be enrolling anything. Exact event IDs depend on what you enabled — the point is: enable the plumbing before you brag about coverage.

What the network looks like when Certipy goes brrr

When I ran the interesting bits, it wasn’t one tidy packet. It was a bunch of certificate request chatter — multiple requests, templates in play, the kind of burst that looks different from “Bob renews a smart card once a year.”

On the wire you’re in RPC / cert services land more than “pretty LDAP filter” land (BloodHound/Rubeus energy). That matters for detection design:

  • LDAP recon tools → often 389 content matches
  • Certipy-style AD CS abuse → more RPC/DCERPC, cert enrollment noise, sometimes SMB-adjacent paths depending on how you’re talking to what

I kept a PCAP labeled something like requesting multiple certs.pcapng in my notes for a reason — replay beats vibes.

Suricata vs DCERPC: welcome to pain

I was on Suricata 6.0.10 in that environment. I wanted something like “alert when we see DCERPC opnum X.”

First attempt energy:

alert dce any any -> any any (
  msg:"DCERPC NetrShareEnum (Opnum 44) Detected";
  dce_opnum:44;
  sid:1000004;
  rev:1;
)

Suricata’s response was basically “lol no”:

ERRCODE: SC_ERR_UNKNOWN_PROTOCOL(124)
protocol "dce" cannot be used in a signature.
Either detection for this protocol is not yet supported
OR detection has been disabled for protocol through the yaml option
app-layer.protocols.dce.detection-enabled

So even if you think DCERPC is enabled in your head, the sensor config / build might not let alert dce parse. Invalid signature, file fails, you sit there staring at Wireshark where opnum 44 is right there in the decode.

Stuff that parsed but didn’t really solve my life:

# "valid" in some setups, still not the win I wanted
alert dcerpc any any -> any any (
  msg:"DCERPC traffic detected";
  classtype:protocol-command-decode;
  sid:1000005;
  rev:1;
)

# looked right, sat on a PCAP that had the traffic, still no fire
alert dcerpc any any -> any any (
  msg:"DCERPC NetrShareEnum Detected";
  dcerpc.opnum:44;
  sid:1000004;
  rev:1;
)

Also got the classic flowbit warnings about dcerpc.rpcnetlogon being checked but not set — which is Suricata’s way of saying your rule pack assumes protocol state that this sensor isn’t building.

Where I landed mentally:

  1. Don’t trust protocol keywords until suricata -T / log says they load clean on that box
  2. If app-layer DCERPC is half-broken, drop to tcp content / raw hex matches from the PCAP (brittle, but honest)
  3. Pair wire detection with CA auditing so you’re not single-threaded on IDS
  4. Threshold early or you’ll alert on every admin who breathes near RPC

Trevor/Brett energy in my notes was basically: when it’s happening live, go raw hex. Yeah. That tracks.

Illustrative “lab only” approach once you’ve extracted bytes from Wireshark:

alert tcp any any -> $DC_OR_CA_SERVERS any (
  msg:"LAB ADCS/RPC pattern - replace with bytes from YOUR pcap";
  flow:to_server,established;
  content:"|...bytes from the opnum/call that mattered...|";
  threshold:type limit, track by_src, count 5, seconds 10;
  classtype:attempted-admin;
  sid:9100100;
  rev:1;
)

I’m not pasting a magic production SID pack here. If you didn’t extract the bytes yourself, you don’t own the rule.

What I’d validate before calling it “detected”

  • Certipy find / request replay on a span port → PCAP labeled
  • Suricata loads rules with zero unknown-protocol errors
  • At least one fire on replay
  • CA audit log shows the enrollment/request you’d expect
  • False positive pass against a day of normal CA traffic if you have it

Hardening side (because detection without prevention is cosplay)

  • Lock down certificate templates (who can enroll, what EKUs, manager approval)
  • Treat ESC1-style templates like production incidents waiting to happen
  • Turn CA auditing on for real
  • Monitor for sudden enrollment spikes from weird accounts

Anyway

Certipy is fun in a lab and annoying on a sensor. The useful lesson wasn’t “opnum 44 bad.” It was: your IDS protocol story and your CA audit story have to both work, or you’re lying to yourself about AD CS coverage.

Related: Rubeus LDAP filters and BloodHound on LDAP — cleaner wire stories than DCERPC, same lab discipline.

Leave a Reply

Your email address will not be published. Required fields are marked *