Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Clearing client root passwords in Solus on an interval
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Clearing client root passwords in Solus on an interval

DamianDamian Member
edited March 2013 in General

So, it's somewhat well known that Solus stores root passwords in its database schema. The reason that they're there is so that it can attempt to reset the root password when an OS reinstall is performed. This does not seem to work 100% of the time, making it more of a liability than a feature.

"But the passwords are encrypted/hashed/salted/voodoo magic/something!" you say. Sure, this is true. However, if the software can decrypt a password, so can an attacker. Therefore, to reduce liability, i've implemented a MySQL feature to automatically empty the 'rootpassword' column on our installation every 5 minutes.

From http://www.sitepoint.com/how-to-create-mysql-events/ :

An event is similar to a trigger. However, rather than running in response to a data change, events can be scheduled to run any number of times during a specific period. In effect, it’s a database-only cron job.

Events have been supported in MySQL since version 5.1. They are ideal for maintenance tasks such as data archiving or report generation which can be scheduled during off-peak times.

Solus is using Mysql 5.1, so we can use events. You'll need to explicitly set the events engine to on, also from http://www.sitepoint.com/how-to-create-mysql-events/ :

MySQL events are executed by a special event scheduler thread. It’s disabled by default so use the following MySQL command can determine whether it’s running:

SHOW PROCESSLIST;

If the scheduler is running, at least two rows will be shown and one will have its user field set to “event_scheduler”. If only one row is returned, the scheduler is disabled and events will not run.

You can ensure the scheduler starts when MySQL is launched with the command-line option --event-scheduler=ON or setting event_scheduler=ON in your MySQL configuration file (my.cnf or my.ini on Windows).

Alternatively, you can start the scheduler from the MySQL command line:


SET GLOBAL event_scheduler = ON;

Now that you've enabled the event handler, you can execute the following SQL for your Solus database:

NOTICE: This information is being offered for utilization on your own good judgement. I'm not responsible for data loss, angry clients, your dog being killed, etc. Make proper backups, and test the event handler on a separate database before committing it to your live database.

CREATE EVENT `ClearPWColumn` 
ON SCHEDULE EVERY 5 MINUTE 
STARTS '2013-03-01 00:00:01' 
ON COMPLETION PRESERVE 
ENABLE 
DO 
UPDATE vservers SET rootpassword = NULL

Every 5 minutes, MySQL will automatically set the contents of every row of the rootpassword column in the vservers table to NULL. This has the effect that, when the client reinstalls their OS, the install script will attempt to set the root password to an empty value, which is not allowed:

A demonstration:

[root@sapphire ~]# vzctl set 106 --userpasswd root:
Running container script: /etc/vz/dists/scripts/set_userpass.sh
Password change failed

Please note that on our installation, this does not result in containers with blank root passwords. Please add a step into your verification after implementation to ensure that on your installation, client containers aren't being installed with blank passwords.

The user will need to set their root password after reinstalling their OS, using the existing functionality in Solus. This method ensures that the client's selected root password only lives in the database for 5 minutes; if you need a more finite interval than this, you could reduce the event interval into the SECOND range, or use TRIGGER instead.

Comments

  • flyfly Member

    cool

  • RyanDRyanD Member

    @Damian

    Any reason you opted for an event over a trigger? Using a trigger instead you could make sure the field is cleared upon entry into the table, basically preventing it from ever existing.

  • @Damian Awesome! Nice to see people actively "fixing" "known problems" in their software!

  • @RyanD said: Any reason you opted for an event over a trigger? Using a trigger instead you could make sure the field is cleared upon entry into the table, basically preventing it from ever existing.

    If the rootpassword field is empty when either the client's account is created in Solus, or when a new VPS is added to the client's account, it seems to break Solus. TRIGGER seems to run immediately without a delay; Solus does not tolerate this.

    I will admit that I've only recently learned about EVENT and TRIGGER; my original plan was to use a shell script of some sort, in a cron job, to clear the column. There may be some sort of "delay" function that i'm missing with TRIGGER.

  • raindog308raindog308 Administrator, Veteran
    edited March 2013

    No, triggers run as part of the db transaction - same time as the insert/update. They're part of the transaction(assuming innodb) so they can be rolled back. You can't set a delay.

  • ATHKATHK Member

    @Damian apparently this site is all the rage - http://www.lowendguide.com/

    ;)

  • RyanDRyanD Member

    @Raindog308

    Exactly, thats why I was opting for the trigger being better.

    However, as @Damian pointed out, solus seems to get angry. It likely writes out to the DB prior to handing off the password and actually pulls it back from the DB again in it's provisioning routine.

    It would make more sense if Solus was storing it in the session state and then writing it out after completion of work with it's dataset. If that was the case the trigger would be our best option.

  • jarjar Patron Provider, Top Host, Veteran

    @Damian You're just a bucket full of awesome.

  • DamianDamian Member
    edited March 2013

    A bit more information: the point of this is to be a good human being; if our database is stolen, there's not the potential for 1000+ root passwords to be disseminated in a single DB dump. Obviously, I do not anticipate such a debacle, but there's always people smarter than me out there...

    @raindog308 said: No, triggers run as part of the db transaction - same time as the insert/update. They're part of the transaction(assuming innodb) so they can be rolled back. You can't set a delay.

    Thanks for the info, looks like it lives on as an EVENT.

    @RyanD said: It likely writes out to the DB prior to handing off the password and actually pulls it back from the DB again in it's provisioning routine.

    Yes, this is robably the issue... I didn't spend much time on troubleshooting a "why". I chose a 5 minute interval after consideration on how often a client reinstalls their OS, and how long I felt comfortable with the password living in the DB.

    I would much prefer that there were some sort of configuration setting in Solus, such as a "Do not store root passwords after OS setup" or something. Would be an extremely easy if-then to not store passwords anymore.

    @ATHK said: apparently this site is all the rage - http://www.lowendguide.com/

    I have not seen it before

    @jarland said: @Damian You're just a bucket full of awesome.

    Most people usually say i'm a bucket full of something else :X

  • raindog308raindog308 Administrator, Veteran
    edited March 2013

    What about a trigger that changes rootpassword to a random string everytime the table is updated/inserted? Then later the event nukes it. Closes the 5-minute window.

  • RyanDRyanD Member

    @raindog308

    If solus is using that password as part of it's provisioning process to provide it back to the end-user, you just gave them the wrong password :)

  • What would happen if/when a VPS is created/reinstalled within seconds of the event being run?

  • raindog308raindog308 Administrator, Veteran

    Ah...I'm solus ignorant but now see how it flows.

  • DamianDamian Member
    edited March 2013

    @raindog308 said: What about a trigger that changes rootpassword to a random string everytime the table is updated/inserted? It would stay in that state until the event nukes it.

    Setting the column to NULL causes the set password function to fail, so any time there's a Solus function that sets password by reading it from the DB, it fails, because null passwords are not allowed. The decision was made to make the function fail, than to set an arbitrary random string. I'm not sure which is better; I'm open to input.

    @RyanD said: If solus is using that password as part of it's provisioning process to provide it back to the end-user, you just gave them the wrong password :)

    That would be fine too. I would much rather that the user log in to Solus and set their root password with the Root Password function, than to have Solus ever try to to save and re-apply it.

    @MiguelQ said: What would happen if/when a VPS is created/reinstalled within seconds of the event being run?

    I'm not sure; that's quite difficult to test. The failure mode regarding TRIGGER that I described was the same effect when the VPS would be provisioned as if the root password had a special character, such as "@", in it.

  • Why not set the root password stored in the solus DB to a random string, since it would only be used when reinstalling or creating a VPS in the middle of the event running.

  • DamianDamian Member
    edited March 2013

    If a random string is desired instead, you'd need to use a TRIGGER, with the statement of:

    UPDATE vservers SET rootpassword = (MD5(RAND()) FROM 1 FOR 32);
    

    Apropos: this is probably not the most truly random function ever.

    Using this with EVENT would be bad, as this would update the entire rootpassword column every 5 minutes.

  • Taking a look at the TRIGGER functionality, it appears to trigger on entire-column, instead of per-row. Someone else might be able to chime in with more information, though.

  • You should probably just make it hourly, 5 minutes is overkill.

    I wonder if solus has the ability to store the salt/encryption key in a safer form (memory) so it can't be stolen with a db/file dump.

  • raindog308raindog308 Administrator, Veteran

    @Damian said: Taking a look at the TRIGGER functionality, it appears to trigger on entire-column, instead of per-row. Someone else might be able to chime in with more information, though.

    No, just for the row(s) in that transaction. For example:


    CREATE TRIGGER nuke_root_pw
    BEFORE INSERT OR UPDATE ON vservers
    FOR EACH ROW
    SET NEW.rootpassword = 'gibberish';

    "FOR EACH ROW" in this context means "the rows that are invoking this trigger" not "for each row in the table". The syntax is a little confusing.

    "NEW." means "the incoming value".

    That code is from memory so may not be perfect but it's close to that.

    http://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html

  • qpsqps Member, Host Rep

    I could see this being a problem if the client starts the OS reload just before the event is scheduled to run, but it isn't finished before the event is run. Since the event is run every 5 minutes, it could be a frequent issue. If you scheduled it to run once a day or something, that could lessen the likelihood that there would be a problem.

    Or, perhaps @soluslabs has other ideas on other options.

Sign In or Register to comment.