Vulnerability Assessment without Vulnerability Scanner

This will be a practical confirmation of my thesis from “Vulnerability scanners: a view from the vendor and end user side“: the scanner for one operating system is easy to make. I also want to demonstrate that data collection and data analysis for Vulnerability Assessment may be successfully performed separately. There is no need to take the data directly from the vulnerable hosts, when it is already stored somewhere else, for example in IT monitoring systems.

Assessment without vulnerability scanner

The opacity of data collection and the need to have a privileged account on the remote host, traditionally causes conflicts between IS and IT departments and complicates implementation of VM process.

So, to detect vulnerabilities on our Linux host we need to know what version of the packages contain vulnerabilities, which versions of packages are installed on our hosts, and learn how to compare versions.

How do I know which versions of packages are vulnerable?

Vulnerable versions of packages are listed in official security bulletins:
RHEL – https://access.redhat.com/errata/RHSA-2016:0304
CentOS – https://lists.centos.org/pipermail/centos-announce/2015-April/021064.html
Debian – http://www.debian.org/security/2015/dsa-3197
Ubuntu – http://www.ubuntu.com/usn/usn-2537-1/

CESA bulletin example

Of course, you will need to parse them first. Or you can just download the same content already parsed and presented in JSON format with Vulners.
download CESA bulletins from Vulners

For example, for zip archive for CentOS: https://vulners.com/api/v3/archive/collection/?type=centos

Bulletin CESA-2015:0800 will be presented in the following form:

  {
    "_index": "bulletins",
    "_id": "CESA-2015:0800",
    "_source": {
      "hash": "61bcac5239341131505fc1983f9e955c7ee32cd42c07d5eac77e2d9d1735aeff"
,
      "modified": "2015-04-14T00:00:00",
      "cvelist": [
        "CVE-2015-0287",
        "CVE-2014-8275",
        "CVE-2015-0292",
        "CVE-2015-0204",
        "CVE-2015-0293",
        "CVE-2015-0289",
        "CVE-2015-0288"
      ],
      "href": "http://lists.centos.org/pipermail/centos-announce/2015-April/0210
64.html",
      "id": "CESA-2015:0800",
      "title": "Moderate openssl Security Update",
      "published": "2015-04-14T00:00:00",
      "type": "centos",
      "references": [
        "http://lists.centos.org/pipermail/centos-announce/2015-April/021064.htm
l"
      ],
      "reporter": "CentOS Project",
      "bulletinFamily": "unix",
      "description": "Upstream details at : https://rhn.redhat.com/errata/RHSA-2
015-0800.html\nUpdate to the following versions:\nCentOS 5:\n\t- openssl-0.9.8e-
33.el5_11.i386.rpm\n\t- openssl-0.9.8e-33.el5_11.i686.rpm\n\t- openssl-0.9.8e-33
.el5_11.src.rpm\n\t- openssl-0.9.8e-33.el5_11.x86_64.rpm\n\t- openssl-devel-0.9.
8e-33.el5_11.i386.rpm\n\t- openssl-devel-0.9.8e-33.el5_11.x86_64.rpm\n\t- openss
l-perl-0.9.8e-33.el5_11.i386.rpm\n\t- openssl-perl-0.9.8e-33.el5_11.x86_64.rpm",
      "cvss": {
        "vector": "AV:NETWORK/AC:LOW/Au:NONE/C:PARTIAL/I:PARTIAL/A:PARTIAL/",
        "score": 7.5
      },
      "affectedPackage": [
        {
          "OS": "CentOS",
          "packageFilename": "openssl-0.9.8e-33.el5_11.x86_64.rpm",
          "packageVersion": "0.9.8e-33.el5_11",
          "packageName": "openssl",
          "operator": "lt",
          "OSVersion": "5",
          "arch": "x86_64"
        },
        {
          "OS": "CentOS",
          "packageFilename": "openssl-perl-0.9.8e-33.el5_11.i386.rpm",
          "packageVersion": "0.9.8e-33.el5_11",
          "packageName": "openssl-perl",
          "operator": "lt",
          "OSVersion": "5",
          "arch": "i386"
        },
        {
          "OS": "CentOS",
          "packageFilename": "openssl-perl-0.9.8e-33.el5_11.x86_64.rpm",
          "packageVersion": "0.9.8e-33.el5_11",
          "packageName": "openssl-perl",
          "operator": "lt",
          "OSVersion": "5",
          "arch": "x86_64"
        },
[...]
        {
          "OS": "CentOS",
          "packageFilename": "openssl-devel-0.9.8e-33.el5_11.i386.rpm",
          "packageVersion": "0.9.8e-33.el5_11",
          "packageName": "openssl-devel",
          "operator": "lt",
          "OSVersion": "5",
          "arch": "i386"
        }
      ],
      "lastseen": "2016-06-22T19:41:12",
      "objectVersion": "1.0"
    },

You can see the patched versions of packages. Detection logic is really simple: if installed version of the package is smaller, than patched version, the package is vulnerable. This kind of detection most VM vendors use. As you see, it doesn’t contain lower bound, so the fact of detection doesn’t mean that you will actually be able to exploit this vulnerability.

How to get information on installed packages and OS version?

Traditional and universal way is to connect to the host via ssh and run a command for package listing. Fortunately, for CentOS you need only this one command, because it contains also package centos-release (redhat-release for Redhat, etc.) with OS version. In Debian-based distributions you should run ‘dpkg –list’ and read from /etc/lsb-release file for this.

So, CentOS packages:

# ssh user@centos-server.corporation.com 'rpm -qa'
user@centos-server.corporation.com's password: 
module-init-tools-3.9-25.el6.x86_64
setup-2.8.14-20.el6_4.1.noarch
basesystem-10.0-4.el6.noarch
libcap-2.16-5.5.el6.x86_64
info-4.13a-8.el6.x86_64
python-2.6.6-64.el6.x86_64
...
centos-release-6-8.el6.centos.12.3.x86_64
...
xfsprogs-3.1.1-19.el6.x86_64
attr-2.4.44-7.el6.x86_64
unzip-6.0-4.el6.x86_64
rootfiles-8.1-6.1.el6.noarch
htop-1.0.3-1.el6.x86_64
perl-Pod-Escapes-1.04-141.el6_7.1.x86_64
python-setuptools-0.6.10-3.el6.noarch
perl-version-0.77-141.el6_7.1.x86_64
perl-Pod-Simple-3.13-141.el6_7.1.x86_64
vim-filesystem-7.4.629-5.el6.x86_64
gpm-libs-1.20.6-12.el6.x86_64
ncurses-base-5.7-4.20090207.el6.x86_64
ncurses-libs-5.7-4.20090207.el6.x86_64
db4-4.7.25-20.el6_7.x86_64
cyrus-sasl-lib-2.1.23-15.el6_6.2.x86_64
nss-softokn-3.14.3-23.el6_7.x86_64
libsemanage-2.0.43-5.1.el6.x86_64
libss-1.41.12-22.el6.x86_64
vim-minimal-7.4.629-5.el6.x86_64
grep-2.20-3.el6_7.1.x86_64

This is an accurate and universal way. However, you will need an account on the scanning host and should somehow minimize privileges of this account.

Another way is to use the snmp.

$ snmpwalk -mALL -v1 -cpublic centos-server.corporation.com .1.3.6.1.2.1.25.6.3.1.2 | head -n 5
HOST-RESOURCES-MIB::hrSWInstalledName.1 = STRING: "module-init-tools-3.9-25.el6"
HOST-RESOURCES-MIB::hrSWInstalledName.2 = STRING: "setup-2.8.14-20.el6_4.1"
HOST-RESOURCES-MIB::hrSWInstalledName.3 = STRING: "basesystem-10.0-4.el6"
HOST-RESOURCES-MIB::hrSWInstalledName.4 = STRING: "libcap-2.16-5.5.el6"
HOST-RESOURCES-MIB::hrSWInstalledName.5 = STRING: "info-4.13a-8.el6"
...

You can even use Nessus to get the list of packages by snmp without authentication (enable plugin 19763 “SNMP Query Installed Software Disclosure”).

Nessus snmp software plugin

As you can see, plugin output contains the list of installed packages. So, if you retrieve scan results through the API (see “Retrieving scan results through Nessus API“) and parse xml report (see “Nessus v2 xml report format“), you can easily get software data for further analysis.

The problem is that the SNMP output does not contain full versions of packages. There are no architectures. If we ignore architectures, it may lead to false positives: for example, bulletin says only i686 package is vulnerable, we have x86_64 package installed, but still mark it as vulnerable. Some monitoring systems may also take package lists via SNMP and will contain package versions without architectures.

The third way is to put an agent, which will upload the lists of packages to some server. There is no need to have an account for scanning, but on the other hand we still need to install the agent on all hosts, launch it automatically, update and make sure that the agent itself has no vulnerabilities. It is also necessary to maintain the server, which will collect package lists, make it accessible for all the hosts. The agented scanning is another world with another headache. But it is also precise and universal way.

How to compare versions of the packages?

Not an obvious question.I would like to warn: don’t use standard algorithms for strings sorting. This is the way to comparison errors and therefore to errors in vulnerability assessment. You should use a proper algorithm suitable for a particular Linux distribution, for example this one is for rpm-based distributions.

You can either try to write your own code to compare versions or use an existing implementation. For rmp-based distributions I use this python code.

Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import vercmp
>>> installed_version = "2.16-5.5.el6"
>>> bulletin_version = "3-1.1.el6"
>>> status = vercmp.vercmp(installed_version,bulletin_version)
>>> status
-1
>>> installed_version = "3-1.1.el6"
>>> bulletin_version = "2.16-5.5.el6"
>>> status = vercmp.vercmp(installed_version,bulletin_version)
>>> status
1
>>> installed_version = "3-1.1.el6"
>>> bulletin_version = "3-1.1.el6"
>>> status = vercmp.vercmp(installed_version,bulletin_version)
>>> status
0

For dpkg-based distributions you may use apt_pkg.version_compare.

In conclusion

In my experience, allows you to detect vulnerabilities as good as Nessus Local Security Checks. The differences are related to some heuristics, when Nessus tries to hide some vulnerabilities in packages, that are not in use (for example, in different versions of linux-kernel).

Don’t forget about the limitations that can still justify the use of the vulnerability scanner:

  1. Port scanning (and scanning without authorization in general) is important feature, that can help you to detect most critical and exploitable vulnerabilities.
  2. Nessus, for example, can point out that the installed version of the operating system is obsolete and OS vendor does not produce new patches and security advisories for it. Such OS is definitely vulnerable, but it is not clear what particular vulnerability are there. You have to make checks of this kind by yourself.
  3. You will not find vulnerabilities in packages with incorrect version built by your own or downloaded from third-party repositories.
  4. Software can be installed from source and very few VM vendors may detect it. I know only Qualys that tries to detect software versions by running binaries with the the keys -v, -V, –version, etc. Installing software from the sources is a bad practice, which makes software upgrades and monitoring of vulnerabilities much more difficult.

12 thoughts on “Vulnerability Assessment without Vulnerability Scanner

  1. Pingback: Vulnerability scanners: a view from the vendor and end user side | Alexander V. Leonov

  2. Pingback: Dealing with Qualys Cloud Agents | Alexander V. Leonov

  3. Pingback: New Vulners.com services for Linux Security Audit and Vulnerability Alerting | Alexander V. Leonov

  4. Pingback: Problems of Vulnerability Prioritization and Detection | Alexander V. Leonov

  5. Pingback: SSH, SFTP, public key authentication and python | Alexander V. Leonov

  6. Pingback: Vulchain scan workflow and search queries | Alexander V. Leonov

  7. Pingback: Making Expect scripts for SSH Authentication and Privilege Elevation | Alexander V. Leonov

  8. Pingback: What’s wrong with patch-based Vulnerability Management checks? | Alexander V. Leonov

  9. Pingback: No left boundary for Vulnerability Detection | Alexander V. Leonov

  10. Pingback: Code IB 2019: Vulnerability Management Masterclass | Alexander V. Leonov

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.