Metasploit-framework: run msfdb as root user

Created on 30 Jul 2019  路  11Comments  路  Source: rapid7/metasploit-framework

Steps to reproduce

I am on an old linux box with a single root user (I can create users but there is a single TTY so I am unable to switch TTY to non root user) and managed to install via the omnibus installer.

However when I try to run the msfdb init step, the console says it has to be from a non user account.

Would it be possible to run it as root?

Expected behavior

Able to run msfdb as root account.

Current behavior

Unable to run.

System stuff

Metasploit version

  • v5.0.39-dev

I installed Metasploit with:

  • [] Kali package via apt
  • [X] Omnibus installer (nightly)
  • [] Commercial/Community installer (from http://www.rapid7.com/products/metasploit/download.jsp)
  • [ ] Source install (please specify ruby version)

OS

Linux and Ubuntu.

question

Most helpful comment

I just got unnecessarily bent out of shape about being denied something when running as root, on the base concept of what that account is supposed to represent.

I, too, find restrictions such as these frustrating, but only when I'm trying to install software on a test system that I don't care about.

maybe I shouldn't be logged in as root on my servers either.

That would be for the best.

it sounds like you're basically talking about that concept as a theoretical best practice, not that the msfdb init does anything especially dangerous

That's about the gist of it.

Here's a few unlikely yet possible pitfalls that immediately come to mind:

The msfdb script runs a bunch of commands with run_cmd (using Open3.popen3) without the full path. Presumably this could pose a risk if you're running as root and have untrusted paths in $PATH. Granted, if you have $PATH issues, you likely have bigger problems. Similar issues may exist for other environment variables.

There's a lot of instances of command injection which could lead to code execution in the event a malicious database config file is present or specified. ie:

@localconf = Msf::Config.get_config_root
@db = "#{@localconf}/db"
@db_conf = "#{@localconf}/database.yml"
def load_db_config
  if File.file?(@db_conf)
    config = YAML.load(File.read(@db_conf))

    production = config['production']

    # [...]

    # get values for development and production
    @options[:db_port] = production['port']
run_cmd("psql -p #{@options[:db_port]} -c \"#{cmd};\" #{db_name}")

Finally, not specifically related to msfdb, and unlikely, but if you download from a meterpreter session, the file is written to the working directory (and clobbers existing files), which may lead to compromise via files such as .rvmrc which may be loaded and executed automatically when browsing directories on the filesystem. Thus browsing untrusted directories in a privileged shell is not a great idea.

All 11 comments

Running databases and database control scripts as root is a generally a bad idea, and I don't see us supporting that use-case. You can switch to a non-root user by using su - USER, run the script, and then return to root by exiting the less-privileged shell.

Closing as answered, if you have any more questions, we generally prefer to get them on IRC or Slack (see instructions on metasploit.com).

Can I request that this be re-opened as a bug? (Or even a regression? I could have sworn that this worked at some point in the past.) In Linux, if you're running as root, you're the superuser, and a script telling you, "no", when you're root is 馃挬 . Receiving the same error when I ask for --help is even worse.

root@EXAMPLENAME-c2:/opt/metasploit-framework# ./msfdb init
Please run msfdb as a non-root user
root@EXAMPLENAME-c2:/opt/metasploit-framework# ./msfdb --help
Please run msfdb as a non-root user

If you're going to make a statement about how running database setup as root is bad, why not make your script account for that and drop privileges during setup? Especially considering that metasploit is a tool where users are going to want to bind privileged ports in many situations, installing as root is probably one of the most common non-latest-kali use-cases.

I'm currently automating the install of metasploit for repeatable builds of cloud C2 infrastructure through ansible. The only user on my system is root, and IMO I shouldn't have to create a new user just to install metasploit because of a non-specific database threat, especially when that database is only listening on localhost. (Or can you please describe the threat more specifically so I can at least understand why this is such a bad idea?)

The only user on my system is root, and IMO I shouldn't have to create a new user

Well there's your problem.

Or can you please describe the threat more specifically so I can at least understand why this is such a bad idea?

https://en.wikipedia.org/wiki/Principle_of_least_privilege

The advice "do not run as root" is as old as time itself.

You can comment out the abort line to skip this check:

  # Bomb out if we're root
  if !Gem.win_platform? && Process.uid.zero?
    puts "Please run #{@script_name} as a non-root user"
    abort
  end

One additional thing, postgresql itself refuses to run as root. Even if we removed that check, it would just error out too. You might have noted that the Kali Linux version of this script does run as root, but under the covers, it switches to the postgres user anyway.

So the only way to make this message go away for the version here would be if it created a user under the covers too, which is even trickier than just asking the user to not run it as root.

@bcoles: I am of course familiar with the concept of least privilege, and perhaps I'm wrong in the end as I'm the one trying to throw caution to the wind for a simple setup process. I just got unnecessarily bent out of shape about being denied something when running as root, on the base concept of what that account is supposed to represent. On top of that, viewing database setup/configuration (not execution) as an administrative task, not being able to do that as root made no sense from where I was sitting.

I appreciate you mentioning that it is possible to just comment out this check, as I think I can make a simple work-around for that with a lineinfile in ansible if I want to do it my way, but in the end, I may have to just acknowledge that if I'm going to write reports stating that people shouldn't be logged in as admin on their desktops, maybe I shouldn't be logged in as root on my servers either.

@busterb: I absolutely realize that postgresql drops privileges to the postgres user by default, which is part of why I was suggesting that if the script doesn't want root that maybe it could automatically drop privileges as well. Indeed, in this situation, my automated process has already got postgresql installed and running as a low-privilege user, I'm just trying to init the database as root, as that's where the rest of my setup process happens. As-is, it's not as though 'postgres' or 'nobody' will have access to the msf ruby environment to be able to run the msfdb program in the first place, so it was looking like I would need to create a new user, set them up with rvm, install metasploit as that user, init the database as that user, and then delete that user just to use the convenience functions provided by msfdb init, which had started feeling not so convenient at that point. Combined with my impression that most users end up executing msfconsole with sudo anyway because they want to bind listeners to 80/443, then the common setup is already effectively running as root, assuming they haven't taken the time to use setcap or authbind to work around default port restrictions.

In the end, I understand what both of you are getting at, and I have some setup steps to re-consider on my end, but with the way this bug was closed, I was really hoping that there was a very specific "if you run the database setup as a privileged user, then it puts the database into an especially vulnerable state where malicious actors can [yadda yadda]", when in the end, it sounds like you're basically talking about that concept as a theoretical best practice, not that the msfdb init does anything especially dangerous when run as root or is somehow processing untrusted input itself. (Or am I still missing something here?)

I just got unnecessarily bent out of shape about being denied something when running as root, on the base concept of what that account is supposed to represent.

I, too, find restrictions such as these frustrating, but only when I'm trying to install software on a test system that I don't care about.

maybe I shouldn't be logged in as root on my servers either.

That would be for the best.

it sounds like you're basically talking about that concept as a theoretical best practice, not that the msfdb init does anything especially dangerous

That's about the gist of it.

Here's a few unlikely yet possible pitfalls that immediately come to mind:

The msfdb script runs a bunch of commands with run_cmd (using Open3.popen3) without the full path. Presumably this could pose a risk if you're running as root and have untrusted paths in $PATH. Granted, if you have $PATH issues, you likely have bigger problems. Similar issues may exist for other environment variables.

There's a lot of instances of command injection which could lead to code execution in the event a malicious database config file is present or specified. ie:

@localconf = Msf::Config.get_config_root
@db = "#{@localconf}/db"
@db_conf = "#{@localconf}/database.yml"
def load_db_config
  if File.file?(@db_conf)
    config = YAML.load(File.read(@db_conf))

    production = config['production']

    # [...]

    # get values for development and production
    @options[:db_port] = production['port']
run_cmd("psql -p #{@options[:db_port]} -c \"#{cmd};\" #{db_name}")

Finally, not specifically related to msfdb, and unlikely, but if you download from a meterpreter session, the file is written to the working directory (and clobbers existing files), which may lead to compromise via files such as .rvmrc which may be loaded and executed automatically when browsing directories on the filesystem. Thus browsing untrusted directories in a privileged shell is not a great idea.

@bcoles : Thank you. I really appreciate the technical explanation with a solid example.

That is a plausible scenario that I had not considered at all, and gives me solid reason why this is a _VeryBad Idea鈩. I guess I know what I'm re-writing in my playbooks next week. 馃槄

On latest kali (2020.3):

kali@kali:~$ msfdb init
[-] Error: /usr/bin/msfdb must be run as root

Oh the irony. 馃槃

i'm a new learner, but this get me confused.
scenario 1 as root: Please run msfdb as a non-root user
scenario 2 no root: try db_nmap with syn scan
[] Nmap: 'You requested a scan type which requires root privileges.'
[
] Nmap: 'QUITTING!'
guess i need to use nmap directly and import output to db

i'm not sure how many other tools requiring root, emmm

scenario 2 no root: try db_nmap with syn scan
[_] Nmap: 'You requested a scan type which requires root privileges.' [_] Nmap: 'QUITTING!'
guess i need to use nmap directly and import output to db

Yes, that would be for the best if you want to use SYN scanning. TCP connect scanning (-sT) should work without root privileges, but is much slower. Alternatively, you could run msfconsole as root.

i'm not sure how many other tools requiring root, emmm

Some of the packet crafting / sniffing modules may require elevated privileges.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miholtz picture miholtz  路  3Comments

XSecr3t picture XSecr3t  路  3Comments

Funeoz picture Funeoz  路  3Comments

handsomebeast picture handsomebeast  路  3Comments

notdodo picture notdodo  路  3Comments