stupid iptables tricks

Click here to load reader

Post on 06-Aug-2015




0 download

Embed Size (px)


Stupid iptables Tricks

Stupid iptables TricksJim [email protected] Bsides Las Vegas 7/28/2010

Who I amNetwork hacker, not OS hackerFavorite language is bashIf a tool exists to do what I want, why re-invent the wheel?Sorry, Frank^2What I get paid to doRetrofit security onto existing productsTry to keep 80% of you from breaking into my product in less than 1 weekTry to make my job go away by convincing my team to write secure codeOverviewDefining the box:Refresher on what iptables isMeasuring the box:How I learned whats in this presentationOutside the box:Automating & abstracting policy creationCreating static tables with dynamic elementsPushing full packets to userspaceIptablesUmbrella termLinux kernel-level stateful packet filterPart of Netfilter iptables is user-facing appIntegrates with PBR & other fun toysLinux characteristicsRich set of optionsMoon-man languageUser-friendly, but picky whom it considers a friendWhy we ignore iptablesIts the Linux firewall, right? We already have a border firewall.Its old technology L4, not L7[Insert Linux vs. Proprietary argument]Linux is a serverWhy we shouldnt ignore iptablesStateful packet filter most common firewall (!)Dynamic (non-destructive) policy updatesRich configuration optionsMultiple complex inter-connected policiesMakes it easy(er) to optimizeNested policiesShorter logic path in common caseVery complex policies for special casesExtensible state tablesExternal hooksPass the entire packet off to a userspace appLimitationsRules exclusive to L2/L3/L4Iptables / ArptablesVulnerable to IP spoofingEverything interesting is at L7Only L7 capability is pattern matchAnyone remember 1st gen IDS?Subject to false positives if not pre-qualifiedOvercoming limitationsThe Wrong WayTOFU auth (Trust On First Use)Not meaty enoughIP spoofing & session stealing can fry TOFUOptional cryptoE.g. SSL cleartext injection / renegotiationDo it all in L7What could possibly go wrong?Business Logic != networkingOvercoming limitationsThe Cheap WayState machine: is the connection in a state which implies that it has been authenticated?Stateful packet filter ESTABLISHED state(TCP session established)How is this different than TOFU?If you dont have a GOOD answer, its not good enoughOvercoming limitationsThe Right WayStrong authNon-persistent: require for every new connectionMandatory cryptoCant hijack / inject on properly implemented cryptoCrypto is an implicit auth of the established sessionHowever: crypto does not imply initial auth anonymous crypto is possibleIPtables cant do this for you Relevance?What does this have to do with iptables?Reminder that no Linux app or service exists in isolationUseful as 1 of multiple layersIPtables can be coupled tightly with additional security tools & methodsAdvantages of using IPtablesAdd a bump in the wire before ANY app.If a problem can be solved in iptables, the app will inherit the solutionIPtables on-box has insight into the appProcess owner, SElinux context, etc.App can have insight & control of IPtablesDisadvantages of Solving Problems in IPtablesThere is more than one way to do itMany ways are wrongHopefully this talk will show some right waysOrigin of this talk: my jobClustered, appliance-based web appProblem: how to add a new node?Fake new node would be badPwn node before added -> pwn clusterProblem 1: Stealth new nodeMust allow real inbound connectionsShould not reveal open ports to just anyoneNot enough time to implement auth

Solution 1: Port knockingCreate policy to allow only inbound traffic which behaves like a real clusterSpecific order:ICMP pingTCP echoBack-end portDatabase portProfit!If not in order, later ports wont openImplementation 1 (Step 1)iptables -A INPUT -p icmp --icmp-type 8 -m recent --name seenping --set-j ACCEPTImplemenation 1 (Step 2)iptables -N ADD_ECHOiptables -A INPUT -p tcp --dport echo-m recent --name seenping --rcheck-j ADD_ECHOiptables -A ADD_ECHO-m recent --name seenecho --set-j ACCEPT(implicit return to INPUT)Can also explicitly specify with -j RETURNImplementation 1 (Step 3)iptables -N ADD_BACKENDiptables -A INPUT -p tcp --dport 8000-m recent --name seenecho --rcheck--seconds 10-j ADD_BACKENDiptables -A ADD_BACKEND-m recent --name seenbackend --set-j ACCEPTImplementation 1 (Step 4)iptables -A INPUT -p tcp --dport 3306-m recent --name seenbackend --rcheck-j ACCEPTProblem 2: Database syncDatabase sync uses 2 opposite (A->B, B->A) TCP connectionsConnection from old to new: see Problem 1Empty database, no interesting dataConnection from new to old: Family jewels exposedMust not open port to just anyone(yes, were using auth)Solution 2: Quid Pro QuoAka Reverse Port KnockingOld node connects to database outboundIPtables tracks outbound connectionExplicitly allows inbound connectionImplementation 2On existing node:iptables -A OUTPUT -p tcp --dport 3306-m recent --name dbout --rdest-j ACCEPTiptables -A INPUT -p tcp --dport 3306-m recent --name dbout --rcheck-j ACCEPTProblem 3: Log ClogFirewall exceptions should be loggedSome protocols are really chattyWindows broadcastsLots of background noiseIPtables doesnt have rich logging solutionSyslog as kernel messageHard to filter kernel facilityPrevious message repeated 5 million timesSolution 3: Seen-It SuppressionAdd source address to specific recency tableLog first time, ignore for next n minutesSuppress the log clogDoesnt log # of ignored packetsSorry, MarcusImplementation 3iptables -A INPUT -p udp --dport 138-m recent --name udp-138 --rcheck --seconds 300-j DROPiptables -A INPUT -p udp --dport 138-m recent --name udp-138 --setiptables -A INPUT -j LOG --log-prefix INPUT-dropiptables -A INPUT -j DROPRecap (So far)Recency tables for:Port knockingReverse port knockingLog suppressionAll within IPtablesVersion 1.3: Data-driven FirewallPlug-In architectureEach app might open different ports in/outEndpoints might be dynamicE.g. defined by user in in GUIVersion 1.3 SolutionXML firewall policy filesDefine inbound/outbound per-plug-inDefinition can also be database entryWatchdog to scan for changesChanges in filesPoll database for changesVersioning of policiesPolicy updates can be dynamic: insert/remove policiesVersion 1.3 Implementation[1 KLOC of perl] - watchdog[1 KLOC of bash] - policy-checker[1 KLOC of perl] - XML-policy-parser[1 KLOC of bash] - iptables policy generatorRevisiting Problem 1: Add AuthPort knocking is an open secretWatch the wire & learn the comboCreate auth shim layerConnect to 1 port for authService adds permission for client to connect to real port use -m recent in iptables policyecho IP > /proc/net/xt_recent/[name]Note: must run as root Persistent PoliciesConfession: my data-driven firewall doesnt actually intelligently modify the policyFlush tables, bulk pushFlushes ESTABLISHED and RELATED tables tooRules will re-add existing connectionsonly if packets come from client to serverWhat about packets from server to client?Destination and Source are a matter of perspective and initial stateImplementing Persistent PoliciesPolicy:iptables -p tcp --dport 8000 -j ACCEPTPersistent reverse policy:iptables -s [local IP] -p tcp --sport 8000--tcp-flags SYN NONE -j ACCEPTAllow packet in the wrong direction if its not the start of a TCP sessionDangerous territory: can reduce stealthnmap -sA will waltz right through if -s omittedPolicy VersioningQuick hack: use commentsiptables -A PUSHDATE -m comment--comment `date +%s`Embed the date the policy is pushed as a commentChain PUSHDATE (0 references)num target prot opt source destination 1 all -- /* 1280187751 */ Expanding the boxaka what I havent actually done yet

Policy logicPattern matching less blindlyQ&D blocking IDSURL filtering per userPolicy LogicEach chain can call other chainse.g. -j ADD_PINGChains can return to their callere.g. -j RETURNDoesnt this sound like function calls?recency tables =~ variablesSo is FWMARKCanonical Firewall PolicyFirewall access rulesadmins can ssh inFirewall stealth ruleNo one else can access the firewallSeries of access/stealth rulesServers, subnets, 3-Tier, etc.Outbound accessLog/Drop allOptimized Firewall PolicyRule of thumb: more policies = more latencyAll packets to firewall go to separate chain-j FIREWALLImplement access / stealth / log / drop / smiteReduce the # of policies for each packet: reduce the overall latencyMore Policy ProgrammingFWMARKAdd mark to packet in kernellocal scope: only in the box, not on the wireiptables -j MARK --set-mark [unsigned int]iptables -m mark --mark [unsigned int]FWMARK is also recognized by:ip rule / policy-based routingipvs (L3 load balancer)FWMARK exampleBind multiple protocols / ports together in a load balancer policyTypical web site: front page is http:80login is https:443content is http:80 againspawn whiteboard http:9012All connections from same client will go to same back end serverFWMARK vs. recencyRecency tables store IP & timestampsuseful for applying rules to an address that has been seen before in a different connectionno port numbers or protocolsFWMARK is per-packetno concept of connectionPotentially interesting in combinationmark all packets from a recent IPApply PBRPattern MatchingArbitrary pattern matches are too coarsePattern with offset:Helps if pattern GUARANTEED to be at that locationTCP options, encapsulation, etc. can move offsetUse chains to pre-qualify dataPort 80? Thats the HTTP_PATTERNS chainDISCLAIMER:I have no actual knowledge of pattern matching in iptablesQ&D blocking IDS 1: block annoyance for 60 secondsiptables -A FORWARD -m recent --name noplacelike--rcheck --seconds 60 -j DROPiptables -A FORWARD -i eth0 -d recent --name noplacelike --set -j DROPExample 2: rolling blockiptables -A FORWARD -m recent --name noplacelike--update --seconds 60 -j DROPiptables -A FORWARD -i eth0 -d recent --