LES security tool, developed and maintained by Z-Labs is the next generation version of the tool designed to assist the security tester/analyst in looking for critically vulnerable (i.e. locally exploitable) Linux machines during manual red tem/pentest engagement. In this post I will describe how the tool works and how to use it effectively.

Too often during the penetration testing engagements or testing drills/maneuvers I observe peer operators just running ./les.sh (without any parameters) then doing cursory analysis of results and moving forward to other testing techniques if none of the exploit stands out from the crowd. Yet, the tool has much more to offer, then that. But first, let’s do a little deep dive into how the LES actually works as it will help us to understand how to use it effectively.

Under the hood

That being said, to do its job and handle many different Linux distributions LES has employed number of heuristic method(s) to achieve its main objectives: generate the list of candidate exploits for a given Linux box in the same time minimizing false postives and false negatives. Additionally - for the sake of practicallity and smooth maintenance - following assumptions has been made while implementing (and maintaining) the tool:

  • ‘tagging’ subsystem (more on it later) focuses on most popular Linux distributions used on the servers: Debian, Ubuntu, RHEL/CentOS
  • userspace analysis subsytem fully supports deb-based and rpm-based distributions. Support for other distrubtions (e.g. Arch) is only partial

Orginally to achieve its goal LES, was processing solely the kernel version (skiping the distro versioning scheme altogether), this approach was inherited from LES predecessor Linux_Exploit_Suggester script. However, this method wasn’t very effective as it was susceptible to false positives problems, yielding the long list of exploits for manual analysis.

As time passed the tool was improved and currently the approach, it takes to generate list of candidate exploits looks like this:

  1. Generate initial exploits list based on kernel version
  2. Check for ‘Tags’ hits for every exploit
  3. Discard exploits that are not applicable based on ‘additional checks’
  4. Calculate internal metric (‘Rank’) for each candidate exploit and order the list based on the calculation

Let’s discuss each step one by one:

Generating list based on kernel version

As already mentioned this is the first step in reducing the number of candidate exploits applicable for the given machine. LES parses the output of uname command to take the exact kernel version installed and compares it with requirements defined for the exploit, e.g. Reqs: pkg=linux-kernel,ver>=4.4,ver<=4.13,....

Checking Tags for match

To limit false positives and further shortlist exploits that are applicable for the system at hand, LES introduces concept of Tags. Tags are simple statements that describe the kernel versions on which given exploit is known to work and could have form of regex, e.g.: Tags: RHEL=6,RHEL=7{kernel:3.10.0-514.21.2|3.10.0-514.26.1}. Tags do not discard the exploits from the candidate list but rather cause the exploit to “go up” in the list in case of tag hit (more on it below).

Discarding exploits that are not applicable

To further condense the canditate exploits list, additional set of requirements (Reqs field) have been introduced to LES: now when adding the exploit to the tool, one can define additional conditions that are required to be met by the exploit, for example:

Reqs: pkg=linux-kernel,ver>=3.2,ver<=4.10.6,CONFIG_USER_NS=y, \
sysctl:kernel.unprivileged_userns_clone==1 

Requirements set from above states that the kernel version needs to be > 3.2 and <= 4.10.6 but also kernel needs to have usernamespace fucntionality compiled in (CONFIG_USER_NS=y) and enabled (sysctl:kernel.unprivileged_userns_clone==1).

For less typical checking, also the ability to run arbitrary Bash command(s) was provided to see if the exploit is applicables for given system, for example:

Reqs: pkg=linux-kernel,ver>=4.4.0,ver<=4.4.0,cmd:grep -qi ip_tables /proc/modules

In above scenario command grep -qi ip_tables /proc/modules is run to verify if ip_tables module is loaded (as this is required for the exploit to work) and exploit is meant applicable for the given system only if this command will return TRUE.

Ordering list based on dynamically generated rank

Finally the exploits that made it so far, are ordered and displayed based on the dynamically calculated Rank the higher the rank (and therefore the position in the list) the higher probability the exploit is applicable for given system.

Rank calculation is based on following simple rules:

  1. Initial rank for “normal” exploit is 1
  2. Initial rank for “great” exploits i.e. (very reliable, applicable for range of distros/kernel versions, includes SMEP/SMAP/KASLR bypass, etc.) is 5. Examples of such exploits: dirtycow, eBPF_verifier.
  3. Initial rank for “poor” exploits (not reliable, known to work only in testing environment, etc.). Examples: keyring exploit.
  4. Add 2 to the current exploit’s initial rank if there’s tested OS distribution version match witch the one from Tags.
  5. Add 5 to current exploit’s rank when there’s a tested OS kernel version regex match with the one from Tags.

So the value of Rank calculated by LES for dirtycow exploit (Tags: ...,ubuntu=16.04{kernel:4.4.0-21-generic},...) and run on Ubuntu 16.04 machine with the kernel in version 4.4.0-21-generic installed is:

Inital rank: 5
Distribution version match: +2 to rank
kernel version regex match: +5 to rank
final rank: 12

Functionality

Okay, we know how the LES works, now lets use it.

Basic use case, all steps (as discussed previously) are performed in order to generate candidate exploits list:

$ ./les.sh

--cvelist-file switch should be used whenever possible (i.e. we have complete listing of CVEs by which our target is affected (for popular Linux distros such list could be generated via https://api-ksplice.oracle.com/api/1/update-list/):

$ ./les.sh --cvelist-file <cve-listing-file>

During red team engagements, on strictly monitored targets (e.g. HIDS) we could be forced to run LES indirectly:

victim-host$ dpkg -l > pkgsListing.txt
pentester-host$ ./les.sh --uname "<uname-a-from-victim>" --pkglist-file pkgsListing.txt

Often before exploiting target machine, its worth to check whether any additional/non-default kernel hardening measure is enabled (e.g. exploit does not have SMEP bypass so lets actually make sure that its disabled):

$ ./les.sh --checksec

For more usage scenarios see README.md in LES Github repository.

Contributing

LES is useful tool used by the security professionals around the globe during their red team/pentest engagements. To make it even better and more effective you can help in 4 ways:

  • Add newly published Linux privilege escalation exploits to it.
  • Test existing exploits on various Linux distributions with multiple kernel versions, then document your findings in a form of Tags in LES, e.g. of a tag: ubuntu=12.04{kernel:3.(2|5).0-(23|29)-generic} which states: tagged exploit was verifed to work correctly on Ubuntu 12.04 with kernels: 3.2.0-23-generic, 3.2.0-29-generic, 3.5.0-23-generic and 3.5.0-29-generic;. With this tag added LES will automatically highlight and bump dynamic Rank of the exploit when run on Ubuntu 12.04 with one of listed kernel versions. This will help you (and others) during pentests to rapidly identify critically vulnerable Linux machines.
  • Published exploits are often written only for PoC purposes only for one (or couple of) specific Linux distributions and/or kernel version(s). Pick sources of the exploit of choice and customize it to run on different kernel version(s). Then add your customized version of exploit as ext-url entry to LES and modify Tags to reflect newly added targets.
  • Conduct analysis of chosen kernel hardening security measure then add it to the FEATURES array (if not already there) and publish your analysis at: https://github.com/mzet-/les-res/blob/master/features/<feature-name>.md.