The Heartbleed vulnerability (CVE-2014-0160) exposed a critical need for accurate OpenSSL version detection. While openssl version
seems straightforward, we hit a major snag in practice:
$ openssl version -a OpenSSL 1.0.1 14 Mar 2012 built on: Tue Jun 4 07:26:06 UTC 2013
The missing patch letter (e.g., 'g' in 1.0.1g) makes this output unreliable for security checks. Let's explore robust detection methods.
Here's a bash script that combines multiple verification approaches:
#!/bin/bash # Method 1: Check build date (most reliable cross-distro indicator) BUILD_DATE=$(openssl version -a | grep -i 'built on') VULNERABLE_DATE="Mon Apr 7 20:33:29 UTC 2014" if [[ "$BUILD_DATE" == *"$VULNERABLE_DATE"* ]]; then echo "[+] Secure build detected" else echo "[-] Potentially vulnerable build" fi # Method 2: Package manager queries if [ -f /etc/debian_version ]; then apt-cache policy openssl libssl1.0.0 elif [ -f /etc/redhat-release ]; then yum info openssl openssl-libs fi # Method 3: Shared library verification ldd $(which openssl) | grep ssl
The discrepancy occurs because:
- Distros often backport security fixes without changing the version string
- The OpenSSL version macro (OPENSSL_VERSION_TEXT) doesn't always include patch letters
- Shared libraries may report different versions than the CLI tool
For developers needing C/C++ integration:
#include#include int main() { printf("Compile-time version: %s\n", OPENSSL_VERSION_TEXT); const char *(*version_func)(int) = NULL; void *handle = dlopen("libssl.so", RTLD_LAZY); if (handle) { version_func = dlsym(handle, "SSLeay_version"); if (version_func) { printf("Run-time version: %s\n", version_func(0)); } dlclose(handle); } return 0; }
When checking for Heartbleed fixes:
- Always check both openssl and libssl packages
- Verify the build date matches post-patch releases (April 2014+)
- Consider using the OpenSSL version API rather than CLI output
- Check for memory-resident old versions with:
lsof -n | grep ssl | grep DEL
For Ubuntu/Debian:
apt-cache policy libssl1.0.0 | grep -E '1.0.1-[1-9]g'
For RHEL/CentOS:
rpm -qi openssl | grep -E 'Version.*1.0.1e-16'
For automated scanning across multiple servers, consider combining these methods with SSH command execution or configuration management tools.
When executing openssl version -a
on Ubuntu 12.04 LTS with OpenSSL 1.0.1g, many administrators observe incomplete version information:
OpenSSL 1.0.1 14 Mar 2012 built on: Tue Jun 4 07:26:06 UTC 2013 platform: [...]
The critical version letter (a-g) is missing from the output, making Heartbleed vulnerability assessment difficult since only versions 1.0.1g and above are patched.
System Package Manager Queries
Debian/Ubuntu:
apt-cache policy openssl apt-cache policy libssl1.0.0
RHEL/CentOS/Fedora:
rpm -qi openssl yum info openssl openssl-libs
Direct Library Inspection
For systems where package managers aren't available:
strings /usr/lib/libssl.so | grep "^OpenSSL [0-9]" strings /usr/lib64/libssl.so.* | grep "^OpenSSL [0-9]"
The patched versions have specific build timestamps:
# Safe versions will show: built on: Mon Apr 7 20:33:29 UTC 2014
This corresponds to the Heartbleed patch release. Any earlier build date indicates vulnerability.
Identify if outdated libraries are still in use:
lsof -n | grep ssl | grep DEL sudo netstat -plant | grep ':443' sudo ss -plant | grep ':443'
Here's a POSIX-compliant shell script for version checking:
#!/bin/sh check_openssl_version() { min_version="1.0.1g" current_version=$(openssl version | awk '{print $2}') printf '%s\n%s\n' "$min_version" "$current_version" | \ sort -C -V -t '.' -k1,1 -k2,2 -k3,3 if [ $? -eq 0 ]; then echo "VULNERABLE: OpenSSL $current_version" return 1 else echo "SAFE: OpenSSL $current_version" return 0 fi } check_openssl_version
The missing version letters occur because many distributions rebuild OpenSSL packages while maintaining the upstream version number. The actual patch status is better determined through:
- Package changelogs (
apt-get changelog openssl
) - Distribution security advisories
- Build timestamps
After upgrade, verify:
sudo ldd $(which openssl) | grep ssl sudo service apache2 restart # or appropriate web server sudo openssl s_client -connect localhost:443 -tlsextdebug 2>&1 | grep heartbeat
The last command should show no heartbeat extension support in patched versions.