BMC network security audit tools
Joseph Reynolds
jrey at linux.ibm.com
Wed Apr 8 08:05:06 AEST 2020
OpenBMC Community,
Here are the BMC network security audit tools as discussed in the
Security Working Group meeting 2020-03-04.
I intend to merge this into the [OpenBMC tools repo][] and use it for
the Security Working Group's input to the [Release Process][]. I would
be happy if these checks were sharpened and added to a dynamic scanner
(but I have no plans to do that myself).
- Joseph
_____
Purpose: Provide shell scripts to expose security aspects of an
operational OpenBMC system from the point of view of an agent on the
BMC's management network trying to get access. The intended use is to
provide information needed to audit the BMC's interfaces, not to perform
a security test. For example, the script detects if the BMC rejects TLS
1.1 and accepts TLS 1.2. The primary value the scripts provide is a
starting point for what to look at, how to get the information, and
where to learn more.
Two scripts are provided.
The first script runs on a system that has access to the BMC's
management network; it uses that access to probe the BMC's network
interfaces. The BMC should be configured for its intended operating
environment, ideally following the [security implementation guidance][]
provided to its users. For example, IP address configured, certificates
added, default passwords changed, etc.
The second script runs on the BMC's shell, typically via SSH. The idea
is to log into the BMC as each kind of BMC user (root, Operator, etc.)
and run the script. You'll need root access to get all the details, and
users with less authority to validate access controls.
The scripts were developed using Linux and the bash shell with the
intent to use the portable subset (no bashisms).
They are not fully automated, and can be run piecemeal as your
investigation requires.
Finally, if you share the results of running this, please redact
sensitive information (such as specific hostnames, usernames, versions,
etc.) that reveal details of your private environment.
[security implementation guidance]:
https://en.wikipedia.org/wiki/Security_Technical_Implementation_Guide
[OpenBMC tools repo]: github.com/openbmc/openbmc-tools
[Release Process]:
https://github.com/openbmc/docs/blob/master/release/release-process.md
_____
# Set up shell variables to represent the test host and BMC environment
# where the "test host" is a system that has network access to BMC.
# Please customize these for your environment.
# Test host environment: What directory to use when commands need to
write files to the test host's file system?
workdir=/tmp
workdir=.
# Access to the BMC
bmc=192.168.123.132 # Change me!
bmcsshport=22
bmcadminuser=root
bmcadminpassword=0penBmc
# Collect data from the test host
# This section has details about the test host used to connect to the
BMC. The test host matters due to the versions of the commands used to
connect to the BMC.
echo "Collecting test host basic data"
hostname
date
uname -a
cat /etc/os-release
echo "Collecting test host user info"
whoami
echo "Checking test host ipmitool version"
ipmitool -V
echo "Checking test host openssl version"
openssl version
ciphers=`openssl ciphers | tr : ' '`
echo $ciphers
# Ping
echo "Testing: Ping the BMC"
ping ${bmc} -c1
# mDNS discovery - or substitute your favorite mDNS discovery tool
echo "Testing: Check for mDNS discovery service"
avahi-browse --all --ignore-local --resolve --terminate
# IPMI
echo "Testing: network (out of band) IPMI"
ipmitool_args="-H ${bmc} -I lanplus -U ${bmcadminuser} -P
${bmcadminpassword}"
echo "Testing: List IPMI users"
ipmitool ${ipmitool_args} user list 1
: Look for users and their privilege
echo "Testing: Print IPMI network settings"
ipmitool ${ipmitool_args} lan print 1
: Look for RMCP+ cipher suites, for example
echo "Testing: Show IPMI supported cipher suites"
ipmitool ${ipmitool_args} channel getciphers ipmi 0x1
ipmitool ${ipmitool_args} channel getciphers sol 0x1
: Look for supported algorithms
: See https://github.com/openbmc/phosphor-net-ipmid files:
auth_algo.hpp, integrity_algo.hpp
: See https://github.com/openbmc/meta-phosphor file:
recipes-phosphor/ipmi/phosphor-ipmi-config/cipher_list.json
# Secure Shell (SSH)
echo "Testing: security aspects of the SSH connection"
ssh -p ${bmcsshport} -vv ${bmcadminuser}@${bmc} echo "Hello OpenBMC"
: Supply the password if needed
: Look for debug data that shows items like: KEX algorithms, ciphers,
and MACs.
: See
https://github.com/openbmc/openbmc/blob/master/poky/meta/recipes-core/dropbear/dropbear/dropbear-disable-weak-ciphers.patch
echo "Testing: SSH SoL connection (port 2200)"
timeout 20s ssh -p 2200 ${bmcadminuser}@${bmc}
: Supply the password if needed
: If the host console is active, look for a login prompt or shell prompt
: Expect the connection to be unresponsive when the host is not up.
: Note the command above (timeout) disconnects after the themeout period.
# HTTP (port 80)
echo "Testing: HTTP"
curl -k -D ${workdir}/http-response-headers -X GET http://${bmc}/redfish/v1
echo $?
: Look for error ("Connection refused") or look at response headers:
cat ${workdir}/http-response-headers
# HTTPS
echo "Testing: HTTP response headers"
curl -k -D ${workdir}/http-response-headers -X GET https://${bmc}/redfish/v1
echo $?
cat ${workdir}/http-response-headers
: Validate HTTP response headers: Content-Security-Policy, etc.
: See https://github.com/openbmc/bmcweb file:
include/security_headers_middleware.hpp
echo "Testing: HTTPS supported ciphers"
# What is the right way to determine supported HTTPS ciphers?
curl -k -v --tlsv1.1 -X GET https://${bmc}/redfish
curl -k -v --tlsv1.2 -X GET https://${bmc}/redfish
: Validate tlsv1.1 reports SSL_ERROR_PROTOCOL_VERSION_ALERT and drops
: Validate tlsv1.2 connects
: See https://github.com/openbmc/bmcweb file: include/ssl_key_handler.hpp
# SSL renegotiation
echo "Testing: SSL renegotiation"
openssl s_client -connect 127.0.0.1:2443
: Note this may report: Secure Renegotiation IS supported
: To renegotiate: type the capital-R letter and press enter
: Validate the RENEGOTIATING response indicates error, no renegotiation
: See https://github.com/openbmc/openbmc/issues/3624
# BMC unauthenticated access
# This probes what you can and cannot access when not authenticated
curl -k -X GET https://${bmc}/ | gunzip
: The unzip command assumes Content-Encoding: gzip
curl -k -X GET https://${bmc}/redfish/
curl -k -X GET https://${bmc}/redfish/v1/
curl -k -X GET https://${bmc}/redfish/v1/JsonSchemas
: Validate access is allowed to the URIs above
curl -k -X GET https://${bmc}/redfish/v1/Registries
curl -k -X GET https://${bmc}/redfish/v1/SessionService
curl -k -X GET https://${bmc}/redfish/v1/SessionService/Sessions
curl -k -X GET https://${bmc}/redfish/v1/AccountService
curl -k -X GET https://${bmc}/redfish/v1/AccountService/Accounts
: Validate access is NOT allowed and we get: Unauthorized
# Probe BMC security settings
: Use admin login to probe security settings. First create a login session:
curl --insecure -X POST -D headers.txt \
https://${bmc}:${bmc_https_port}/redfish/v1/SessionService/Sessions \
-d '{"UserName":"'${bmcadminuser}'",
"Password":"'${bmcadminpassword}'"}' | tee ${workdir}/results.txt
authtok=$(grep "^X-Auth-Token: " headers.txt | cut -d' ' -f2 | tr -d '\r')
test -n "${authtok}" && echo "Got X-Auth-Token okay (in shell variable
authtok)" || { echo "Failed to get X-Auth-Token" && false; }
sessid=$(grep -e '"Id":' ${workdir}/results.txt | cut -d\" -f4)
echo "sessid='${sessid}'"
: then use the session (authtok) below.
curl -k -H "X-Auth-Token: ${authtok}" -X GET
https://${bmc}/xyz/openbmc_project/software/attr/FieldModeEnabled
: Validate data (boolean)
curl -k -H "X-Auth-Token: ${authtok}" -X GET
https://${bmc}/redfish/v1/AccountService property
: Validate AccountLockoutDuration, AccountLockoutThreshold,
: LDAP.ServiceEnabled, Oem.OpenBMC.AuthMethods
_____
# Run these commands on the BMC's shell, for example via SSH.
# This should be repeated for several BMC users:
# - root
# - A non-root Administrator user
# - An Operator user
# - A ReadOnly user
# Create testuser id, authorize that id to use ssh, and ssh into the BMC.
# May need to run this on the bmc to grant SOMEUSER access to SSH:
# sudo usermod --append --group ssh SOMEUSER
echo "BMC check: get basic information"
hostname
date
uname -a
cat /etc/os-release
echo "BMC check: username and group membership"
whoami
groups
: Validate groups. Note the group prefixed with "priv-" denotes the
privilege role.
: See
https://github.com/openbmc/docs/blob/master/architecture/user_management.md#supported-privilege-roles
:
https://github.com/openbmc/docs/blob/master/architecture/user_management.md#supported-group-roles
: For example, a result of "priv-admin ssh redfish" indicates a
privilege role of admin and authorized to the ssh and redfish groups.
echo "BMC check: access to files in /home/root"
ls -lR /home/root
echo "BMC check: access to files in /var/log"
ls -l /var/log
echo "BMC check: access to files in /etc"
ls -l /etc
head -3 /etc/shadow
ls -l /etc/certs
ls /home/root/
ls -lR /etc/ssl
: Validate file permissions and acces to files
echo "BMC check: Validate PAM config"
ls -R /etc/pam.d
(cd /etc/pam.d; ls | xargs tail -n +1)
: Validate contents of PAM config files
# What other checks and tests are needed?
# Is there a test for randomness and entropy?
More information about the openbmc
mailing list