So on twitter, I see this: https://twitter.com/nicoleperlroth/status/1392196162493444098 which has an image that reads how along with unpatched Exchange, they were also exposing SNMP, NTP, and DNS to the public internet.
Sigh
DNS, depending on details I’m not surpried. But NTP and especially SNMP? That’s…there’s no excuse for SNMP exposed to the public internet. None. There’s no way that’s not an awful idea. Because SNMP isn’t just router packet counts. An example, taken from a Brocade switch:
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntName.<username> = STRING:
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntName.<username> = STRING:
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntPassword.<username> = STRING: <hashed password>
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntPassword.<username> = STRING: <hashed password>
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntEncryptCode.<username> = INTEGER: 8
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntEncryptCode.<username> = INTEGER: 8
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntPrivilege."<username> = INTEGER: 0
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntPrivilege.<username> = INTEGER: 0
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntRowStatus.<username> = INTEGER: valid(2)
.iso.org.dod.internet.private.enterprises.foundry.products.switch.snAgentSys.snAgentUser.snAgentUserAccntTable.snAgentUserAccntEntry.snAgentUserAccntRowStatus.<username> = INTEGER: valid(2)
That’s a fairly standard set of OIDs. They show up in HP gear as well. Since Brocade bought foundry some time ago, that table lives in a lot of stuff. The details on this are available at http://www.circitor.fr/Mibs/Mib/F/FOUNDRY-SN-AGENT-MIB.mib (Seriously, for finding MIBS and stuff, circitor is amazing). From that MIB:
snAgentUserAccntName OBJECT-TYPE SYNTAX DisplayString (SIZE (1..48)) MAX-ACCESS read-only STATUS current DESCRIPTION "The user name." ::= { snAgentUserAccntEntry 1 } snAgentUserAccntPassword OBJECT-TYPE SYNTAX DisplayString (SIZE (0..48)) MAX-ACCESS read-write STATUS current DESCRIPTION "The user password." ::= { snAgentUserAccntEntry 2 } snAgentUserAccntEncryptCode OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-write STATUS current DESCRIPTION "The password encryption method code." ::= { snAgentUserAccntEntry 3 } snAgentUserAccntPrivilege OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-write STATUS current DESCRIPTION "The user privilege." ::= { snAgentUserAccntEntry 4 } snAgentUserAccntRowStatus OBJECT-TYPE SYNTAX INTEGER { other(1), valid(2), delete(3), create(4), modify(5) } MAX-ACCESS read-write STATUS current DESCRIPTION "To create or delete a user account table entry." ::= { snAgentUserAccntEntry 5 }
Note something here: the user name is read-only, but the rest? Read-Write, and snmpset is not a hard command to master. At all.
But it gets…better. See, if you allow SNMPv anything less than 3, then none of your stuff is encrypted. It’s all plain text, protected by a single password that is also sent and received in plain text. No really, from an SNMP v1/2/2c packet:
Simple Network Management Protocol
version: v2c (1)
community: bynkii
data: get-response (2)
get-response
request-id: 240098041
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.2.1.1.3.0: 85515481
Object Name: 1.3.6.1.2.1.1.3.0 (iso.3.6.1.2.1.1.3.0)
Value (Timeticks): 85515481
See that bit in bold? Yeah, that’s the password/community string. In the packets. That are exposed to the internet.
I don’t know for sure that Colonial had SNMPv2 running, but in my experience, given how tedious some vendors make setting up SNMPv3, I’d put it at 80%-90% they had that running. Which means, unless they spent a lot more time on SNMPvNot3 security other than maybe changing the default community strings from “public” and “private”, which is really rare, once you have the community string, you potentially have a LOT of data available to peruse.
Aside from potential user credentials, if I can read the right gear, I can get IP addresses, MAC addresses and all kinds of info for everything that communicates with the device I’m querying. If it’s a core router or firewall…I have a lot of Very Useful Information on your network just with a single run of snmpwalk. Go read that entire MIB file I linked to, see how much info is available. And that’s minor.
SNMPv3 isn’t perfect, but at least it allows for authentication protocols and encryption protocols and each has a proper username and passphrase that can be completely different from each other on a per-device basis. You can also better lock down what a given set of credentials can access.
But the larger, the much larger issue is there is no reason to have SNMP visible from the public internet. At worst that should only travel the internet in a very heavily locked-down VPN, but even then, if there’s not a critical need for that, don’t do it. So in a nutshell:
- Kill SNMPv2 on your network dead. Yes, I know, Windows. Use WMI for Windows. Yes I know, it’s more work. Do that work.
- DON’T LET ANY SNMP TRAFFIC ON THE DAMNED PUBLIC INTERNET.
Jesus, at least make the hackers do a little work for that info.