Attacker Value
Very High
(1 user assessed)
(1 user assessed)
User Interaction
Privileges Required
Attack Vector


Disclosure Date: May 11, 2020
Add MITRE ATT&CK tactics and techniques that apply to this CVE.


The Gravity updater in Pi-hole through 4.4 allows an authenticated adversary to upload arbitrary files. This can be abused for Remote Code Execution by writing to a PHP file in the web directory. (Also, it can be used in conjunction with the sudo rule for the www-data user to escalate privileges to root.) The code error is in gravity_DownloadBlocklistFromUrl in

Add Assessment

  • Attacker Value
    Very High
  • Exploitability
Technical Analysis

Works against pi-hole <=4.4, which was just about recent at the time of release.
Excellent write-up here:

The CVE encompasses a file overwrite, however overwriting the right files can escalate privs.
The CVE is basically that a new blocklist can be added, and then an update is forced (gravity is pihole terminology for this) to pull in the blocklist content. PHP content is then written to a file within the webroot.

How the real chain of exploit works is this:

  1. writes a sudo pihole command to launch teleporter, effectively running a priv esc. sudo pihole -a -t is the command to do this. pihole is in sudoers, so we won’t need to provide a password. This file is stored at an arbitrary location within the webroot.
  2. writes our payload to teleporter.php, overwriting, the content.
  3. visit the arbitrary file set in phase 1, which launches the pihole command. -t executes teleporter.php, which gives us a root shell.

Most of the restrictions for this exploit are focused around adding the blocklist. Due to encoding, formatting, etc, we are only able to provide an IP. No port, or file name.

With this in mind, exploitation takes many steps. In theory, w/o these restrictions, you’d set 2 block lists (phase 1, and 2), update gravity twice to pull in the files, and done. You would have set each block list to a diff URL thus being able to differentiate them.

However, since you aren’t able to do that, the actual chain looks more like this:

  1. add blocklist for phase 1
  2. update gravity and 200 OK the request
  3. update gravity and send back your phase 1 command.
  4. add blocklist for phase 2
  5. update gravity and 200 OK the request
  6. update gravity and send back your phase 2 command.
  7. hit the URL stored for phase 1.

General Information

Technical Analysis