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