Bug 1097022 - ovirt-engine-setup: weak default passwords for PostgreSQL database users
Summary: ovirt-engine-setup: weak default passwords for PostgreSQL database users
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: oVirt
Classification: Retired
Component: ovirt-engine-installer
Version: 3.4
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
: 3.4.2
Assignee: Sandro Bonazzola
QA Contact: Pavel Stehlik
URL:
Whiteboard: integration
Depends On:
Blocks: 1097023 1103976
TreeView+ depends on / blocked
 
Reported: 2014-05-13 02:20 UTC by Murray McAllister
Modified: 2015-01-04 22:40 UTC (History)
14 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
: 1103976 (view as bug list)
Environment:
Last Closed: 2014-06-19 07:51:12 UTC
oVirt Team: ---
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 1111066 0 unspecified CLOSED [RFE] Docs: oVirt Hardening Guide 2023-05-31 09:28:55 UTC
Red Hat Bugzilla 1111093 0 high CLOSED [Docs][Change][async]Update hardening guide with postgres hints 2021-02-22 00:41:40 UTC
oVirt gerrit 27615 0 None None None Never
oVirt gerrit 27633 0 None None None Never
oVirt gerrit 27635 0 None None None Never

Internal Links: 1111066 1111093

Description Murray McAllister 2014-05-13 02:20:09 UTC
When automatically setting up a PostgreSQL database with engine-setup, weak passwords were generated for the PostgreSQL users. This would make it easier for an attacker to guess passwords and gain access to the Red Hat Enterprise Virtualization Manager database, allowing them to control the virtualization environment.

The PostgreSQL database is accessible remotely with a default Red Hat Enterprise Virtualization Manager installation.

Acknowledgements:

Red Hat would like to thank Michael Samuel of Amcom for reporting this issue.

Comment 2 Murray McAllister 2014-05-13 02:28:55 UTC
PostgreSQL being accessible by default may be a regression, https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Virtualization/3.3/html/Installation_Guide/Database_Server_Firewall_Requirements1.html suggests remotely accessible is not the default

Comment 3 Murray McAllister 2014-05-13 02:33:18 UTC
(In reply to Murray McAllister from comment #2)
> PostgreSQL being accessible by default may be a regression,
> https://access.redhat.com/site/documentation/en-US/
> Red_Hat_Enterprise_Virtualization/3.3/html/Installation_Guide/
> Database_Server_Firewall_Requirements1.html suggests remotely accessible is
> not the default

I think I read that section wrong. Regardless, the documenation likely needs updating too.

Comment 4 Michael Samuel 2014-05-13 05:03:05 UTC
Just to see where the entropy is coming from:

/usr/lib64/python2.6/random.py: look at Random().seed() (with None argument)

        if a is None:
            try:
                a = long(_hexlify(_urandom(16)), 16)

So the RNG is getting initialized with a 128-bit "long" value, which goes to
_randommodule.c in the python source code random_seed():

    if (PyInt_Check(arg) || PyLong_Check(arg))
        n = PyNumber_Absolute(arg);

So now we're down to 127 bits? (or are we down to 63?)

Keep in mind we're at 47 bits (62^8) for the 8-char password.

So assuming we're not leaking more info about the MT state some other way, the weak link seems to be the 8 character password.

So I guess this could be 4 hardening tasks:
- Use SystemRandom to harden against other usage of Random() leaking the password
- Block postgresql remote access for the engine user in pg_hba.conf
- Block postgresql connections in iptables (by default?)
- Increase password length to prevent increase time for successful online bruteforce. (Offline brute-force is not necessary with postgres md5 auth - just use the hash to login)

Comment 5 Sandro Bonazzola 2014-05-13 08:44:22 UTC
(In reply to Murray McAllister from comment #2)
> PostgreSQL being accessible by default may be a regression,
> https://access.redhat.com/site/documentation/en-US/
> Red_Hat_Enterprise_Virtualization/3.3/html/Installation_Guide/
> Database_Server_Firewall_Requirements1.html suggests remotely accessible is
> not the default

PostgreSQL accessible by default is for a RFE allowing read only user to connect to the DB from different host. It's also required for new 3.5.0 features.

Comment 6 Sandro Bonazzola 2014-05-13 08:46:00 UTC
(In reply to Michael Samuel from comment #4)
> Just to see where the entropy is coming from:
> 
> /usr/lib64/python2.6/random.py: look at Random().seed() (with None argument)
> 
>         if a is None:
>             try:
>                 a = long(_hexlify(_urandom(16)), 16)
> 
> So the RNG is getting initialized with a 128-bit "long" value, which goes to
> _randommodule.c in the python source code random_seed():
> 
>     if (PyInt_Check(arg) || PyLong_Check(arg))
>         n = PyNumber_Absolute(arg);
> 
> So now we're down to 127 bits? (or are we down to 63?)
> 
> Keep in mind we're at 47 bits (62^8) for the 8-char password.
> 
> So assuming we're not leaking more info about the MT state some other way,
> the weak link seems to be the 8 character password.
> 
> So I guess this could be 4 hardening tasks:
> - Use SystemRandom to harden against other usage of Random() leaking the
> password
> - Block postgresql remote access for the engine user in pg_hba.conf
> - Block postgresql connections in iptables (by default?)
> - Increase password length to prevent increase time for successful online
> bruteforce. (Offline brute-force is not necessary with postgres md5 auth -
> just use the hash to login)

I think only password hardening and use of SystemRandom can be applied.

Comment 7 Sandro Bonazzola 2014-05-13 09:01:59 UTC
Patch pushed upstream master, Michael, Murray, can you please review?

Comment 11 Michael Samuel 2014-05-13 23:15:32 UTC
So the hardening of passwords looks good.

Some notes from a deeper investigation:

random.choice() == random.Random().choice() - this is a mersenne twister, which provides a good spread, but the RNG state can be reconstructed from other output.  Other outputs are the CA certificate (the number at the end of the CN) and the MAC address range.

Random().choice(), which is inherited by SystemRandom does x[int(self.random() * len(x))].  In this case, 53 bits of entropy is retrieved from /dev/urandom, and converted into a double in the range [0..1].  This is probably unbiased enough for our purposes (although it should probably be using round()).  Changing the password character set to a power of 2 would not significantly remove bias.

Postgres is still available remotely in the default install, including connecting as the engine user.  I'll write some hardening notes and attempt to push upstream.

Comment 12 Michael Samuel 2014-05-13 23:39:34 UTC
Postgres can be hardened by default in plugins/ovirt-engine-setup/provisioning/postgres.py - search for the string "for address in ('0.0.0.0/0', '::0/0')" - that should be "for address in ('127.0.0.1/32', '::1')".

This would allow users to add remote users for dwh on their own, but lock down the system users.

Comment 13 Sandro Bonazzola 2014-05-14 07:08:36 UTC
(In reply to Michael Samuel from comment #11)

> Postgres is still available remotely in the default install, including
> connecting as the engine user.  I'll write some hardening notes and attempt
> to push upstream.

Thanks, please add me and didi as reviewers.

Comment 14 Sandro Bonazzola 2014-05-19 08:20:45 UTC
Patch for using SystemRandom and 22 chars merged on upstream (3.3, 3.4 and master) and downstream (3.4.0 and 3.3) gerrit.

Michael ETA about your patch?

Comment 15 Kurt Seifried 2014-05-19 20:15:49 UTC
This one is definitely security hardening and not a security
vulnerability, the password contains 47 bits of entropy, so that's
1.4073749e+14 passwords, assuming a million guesses a second that
means on average it will take 814 years to guess the password, and
obviously that many password attempts would kill the server, let alone
be noticed by the admin and stopped at some point. So it can be fixed,
but it won't be a security vulnerability (so no CVE/etc.).

Comment 16 Michael Samuel 2014-05-19 22:00:20 UTC
Hi Kurt,

You missed the part about non-exclusive use of mersenne-twister to generate the passwords (which was the impetus for the report - I just suggested hardening while we're editing that line).

So potential vulnerability:
Use of python random.choice() to generate password.  The same RNG is used to add an integer to the end of the CA certificate and for 16 bits of the MAC address pool.

Exposure:
pg_hba.conf has "all" in the host field for all entries (generated by the engine-setup script) and the postgres port is open in iptables rules generated by the same script

Hardening done:
Increase number of characters to meet a better standard of secure (>128 bits)

Hardening not done (yet?):
- Change how engine-setup generates pg_hba.conf: only allow the engine user to connect from 127.0.0.1/32, possibly use the more secure 'password' rather than 'md5'
- Ask administrator whether postgres should be allowed in engine-setup generated iptables rules

I was planning on implementing the not-done hardening in a 'hardening guide', but I think those files are clobbered by engine-setup during upgrades.

Comment 17 Michael Samuel 2014-05-21 03:31:42 UTC
Ok, so here's how my pg_hba.conf looks:

local   all         postgres                                  ident
host    rhevmreports    engine_reports  127.0.0.1/32          password
host    rhevmreports    engine_reports  ::1/128               password
host    all             engine_history  127.0.0.1/32          password
host    all             engine_history  ::1/128               password
host    engine          engine          127.0.0.1/32          password
host    engine          engine          ::1/128               password

I don't think this is hardening guide stuff - if the engine is managing the database it should just set it up like this. I'm using password rather than md5, because then the hash in pg_shadow needs to be cracked before it can be used - with md5 auth it can be used directly (eg. if found in a backup dump).

If remote connections are to be allowed for a specific user (or set of users), then that should get it's own entry.

Comment 18 Alon Bar-Lev 2014-05-21 07:56:53 UTC
Hello Michael,

In order to provide support for product, the product enables remote access to database by default. In the near future we will also support multiple servers configuration, this will require remote access to database.

If administrator wishes to harden the server he can do this at any point:

1. pre installation - select "Manual" instead of "Automatic" and setup database manually as he wishes so, providing the host, user, password, database name. The product is not managing the database in any other sense.

2. post installation - use iptables or pg_hba modification to limit the source address.

This belongs to hardening guide, just like any other product that uses database.

For the password issue, passing password over the network is something that should be avoided these days. Access to raw backup material may also include plain password as written in product configuration files.

We follow postgresql guide[1]:
"Plain password should always be avoided if possible."

In any case, per above, user can always modify md5->password if so he wishes, pre/post installation. So this also belongs to hardening guide.

Thanks,

[1] http://www.postgresql.org/docs/9.1/static/auth-methods.html#AUTH-PASSWORD

Comment 19 Kurt Seifried 2014-05-27 23:49:48 UTC
(In reply to Michael Samuel from comment #16)
> Hi Kurt,
> 
> You missed the part about non-exclusive use of mersenne-twister to generate
> the passwords (which was the impetus for the report - I just suggested
> hardening while we're editing that line).
> 
> So potential vulnerability:
> Use of python random.choice() to generate password.  The same RNG is used to
> add an integer to the end of the CA certificate and for 16 bits of the MAC
> address pool.
> 
> Exposure:
> pg_hba.conf has "all" in the host field for all entries (generated by the
> engine-setup script) and the postgres port is open in iptables rules
> generated by the same script
> 
> Hardening done:
> Increase number of characters to meet a better standard of secure (>128 bits)
> 
> Hardening not done (yet?):
> - Change how engine-setup generates pg_hba.conf: only allow the engine user
> to connect from 127.0.0.1/32, possibly use the more secure 'password' rather
> than 'md5'
> - Ask administrator whether postgres should be allowed in engine-setup
> generated iptables rules
> 
> I was planning on implementing the not-done hardening in a 'hardening
> guide', but I think those files are clobbered by engine-setup during
> upgrades.

Right, so as I understand it (please correct me if I'm wrong) none of this stuff is directly exploitable, it's all security issues that require hardening, as such no CVE's will be assigned/etc.

-Kurt

Comment 20 Michael Samuel 2014-05-28 00:13:41 UTC
(In reply to Kurt Seifried from comment #19)

> Right, so as I understand it (please correct me if I'm wrong) none of this
> stuff is directly exploitable, it's all security issues that require
> hardening, as such no CVE's will be assigned/etc.

This depends on the difficulty of obtaining candidate seeds given the 3 outputs (2 x 8bit integers, and a number between 10000-99999), which is a research problem as far as I can tell.

There is probably a number for the amount of offline computation per candidate and the number of candidates, but I don't know what it is yet.

I certainly won't be leaving the passwords unchanged on my own systems.

Comment 21 Sandro Bonazzola 2014-06-19 07:45:01 UTC
Proposed patches have been already merged.
I'll open a bug on doc installation guide for creating an hardening guide we don't have right now.
Started discussion about hardening guide on mailing list.
http://lists.ovirt.org/pipermail/users/2014-June/025244.html


Note You need to log in before you can comment on or make changes to this bug.