WP-CLI is a command line interface for WordPress. It is a nice and very helpful tool if you want to manage a lot of WordPress installations from a Unix shell.
Lately, after cleaning-up a hacked WordPress website, I was checking the HTTP server logs in order to find out how hackers gained access to the site. It didn’t take long to find this suspicious entry:
"GET /wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=../../../../../../../../.bash_history HTTP/1.1" 200 3922 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)" "-"
It shows that someone exploited a recent vulnerability known as Local File Inclusion (or LFI) in the Site Editor plugin. This kind of exploit lets you access, download or view files from the remote server. The downloaded file was “.bash_history”, which is used to store the user commands entered at the command prompt, and is located in the user home folder.
Inside the file, among many other commands, I found this interesting one:
wp user create support [redacted]@gmail.com --role=administrator --user_pass=[redacted]
Our customer, who’s an avid WP-CLI user, used it to create a WordPress administrator account but he forgot one important detail: shell commands are saved to the “.bash_history”, and thus the whole command leaks the admin login name and password. Obviously, after downloading this file, it wasn’t difficult for hackers to gain access to the admin dashboard.
Inserting credentials or any confidential data in a shell command (be it WP-CLI or MySQL for instance) is extremely insecure:
- The command is saved to the “.bash_history” file; it can also be viewed by running the
- Other users on the same server might view the whole command and credentials with the Unix
Fortunately, WP-CLI has a
--prompt option which can be used to ask for the password (and basically any other options) rather than leaking it to the whole world. In this example, I’m safely creating an “alice” admin account:
$ wp user create alice email@example.com --role=administrator --prompt=user_pass
WP-CLI will prompt for the password: