How to add users, create passwords, and limit them to sftp in 4 steps.

HatopHatop Alabama
edited December 2011 in Science & Tech
As is often the case, I'm given a project with a preset due date. Specifically, about 4 weeks of time to plan, implement, test, and put in production a brand new webserver environment. Most of the issues are relatively simple to handle(install apache, mysql, php, move data, import sql, etc). However, one area that needs improvement is user security. The old environment was very old, with its original configuration dating from 2001ish. Since much has changed in the proceeding 10 years, its now time for a security review thanks to the finally approved migration. One large glaring problem is user permissions. I have around 100 users that need file system access to the server. Of these 100 users, 4-5 have actually been trained on using a shell or even a GUI ftp client.

So here are the goals of this walk through on minimal security for a multi-user web host. I'll try to provide a followup walkthrough on actually securing the host, once I'm able to find the time.

1. We need to add 100~ users to this server
2. We need to assign new randomly generated passwords and store them in a human readable way to hand them over to the users
3. We need to keep most of the users from directly accessing the shell
4. We need to encrypt the login information and data transfers to and from the server


Lets begin with tasks numbered 1 and 2. To begin with, we don't want to bother doing this manually. Scripting this process can also save us time when we need to create other users in the future OR for setting up other multi-user environments.

DISCLAIMER: My perl skills are sub-standard at best, so be kind. This code works, but I can't promise security or infallibility.

Here is the perl script we will be using to add users, generate a password, store the user and password combo, and exit.
#!/usr/bin/perl
#installation follows: 
#perl -MCPAN -e shell
#install String::MkPasswd
#Remember to run both the perl install as root and this script.
use String::MkPasswd qw(mkpasswd);
#file is in standard passwd format. Just remember to only include the users #you want to add
open(PASSWD, '/home/youruser/passwd');
open(SAVEFILE, '>>userinformation');
$count=0;
while (<PASSWD>) {
chomp;
($login, $passwd, $uid, $gid, $gcos, $home, $shell) = split(/:/);
@usernames[$count]= $login;
@homedir[$count] = $home;
@shell[$count] = $shell;
@gcos[$count] = $gcos;
@password[$count] = mkpasswd(-length=>10, -minspecial=>0);
$count+=1;
}
close(PASSWD);
$count=0;
foreach $element (@usernames){
#debug statement below
#print "username: $usernames[$count] password: $password[$count] home directory: $homedir[$count] shell: $shell[$count] comment: $gcos[$count] \n";
@userinformation[$count] = "username: $usernames[$count] password: $password[$count] home directory: $homedir[$count] shell: $shell[$count] comment: $gcos[$count] \n";
print SAVEFILE $userinformation[$count];
system("groupadd $usernames[$count]");
system("useradd -g other -G $usernames[$count] -d $homedir[$count] -s /usr/libexec/openssh/sftp-server -c \"$gcos[$count]\" $usernames[$count]");
system("/home/youruser/changepass $usernames[$count] $password[$count]");
$count+=1;
}
close(SAVEFILE);



and the expect script at the end called changepass:
#!/usr/bin/expect --

# Usage: change_one USERNAME NEWPASSWORD
spawn passwd [lindex $argv 0]
set newpass  [lindex $argv 1]
#spawn passwd [lindex $argv 0]
expect "New UNIX password: "
send "$newpass\r"
expect "Retype new UNIX password: "
send "$newpass\r"
expect eof

Now to complete steps 3 and 4. In order to keep a user from actually creating a shell environment, we need to limit how they connect to this server. Thankfully, RHEL does provide a sftp shell that we can assign to each user. It is located in /usr/libexec/openssh/sftp-server . Hence the passwd line for a given user will look something like this:
NewUser:x:501:502::/var/www/website.com/:/usr/libexec/openssh/sftp-server

At this point, the only thing we lack is jailing each user to their own directory. This is a more complicated topic that is OS dependent. Hopefully I can update this with how to selectively lock user accounts to home directories using ssh/sftp.

Any critiques or discussion is welcome on this.

Disclaimer: I make no guarantees to the effectiveness, usefulness, safety, security, or quality of my code or plans. Do not use this code without understanding whats going on.

Comments

  • HatopHatop Alabama
    edited December 2011
    Addendum to the original post:

    I also needed to set permissions across the filesystem for the users generated in the previous post. In order to accomplish this, I set out to script one last part of my current project; User Permissions.

    One caveat to this job is that I can't change the permission set used in the production, hence the shared group across all accounts. I do promise to write up my security walk through once I'm done with the project. On to the code!
    #!/bin/bash
    
    _USERS="$(grep -v nfs /etc/passwd | awk -F':' '{if ($3 >= 500)  print $1}')"
    for u in $_USERS
    
    do
     _dir="$(grep $u /etc/passwd | awk -F':' '{print $6}')"
    
    if [[ -e $_dir ]]
    then
            chown -R $(id -un $u):"other" "$_dir"
    echo -e "$_dir \n $u \n"
    sleep .5
    fi
    done
    

    Explanation of code:

    This short script begins by gathering the users we want to assign permissions for from /etc/passwd. These are collected into an array which we then step through using the for loop. Inside the loop we find the specific user inside /etc/passwd and print the directory out into another array. We then test if the directory exists with the if statement. If it does, we change ownership recursively, sleep for half of a second, and repeat until done.
  • shwaipshwaip bluffin' with my muffin Icrontian
    edited December 2011
    I usually like to throw 'use strict;' at the top of any important perl code to make sure I don't do anything unsafe/dumb.
  • HatopHatop Alabama
    edited December 2011
    shwaip wrote:
    I usually like to throw 'use strict;' at the top of any important perl code to make sure I don't do anything unsafe/dumb.

    Is it possible to edit the original? The link to the edit function doesn't appear for it. I'll make the change in the actual script I used. Thanks for the tip.
  • HatopHatop Alabama
    Since I said I write up my security walk through, I figured I should.

    We didn't do one. Also, in that time I've found a new job and no longer manage web servers.
Sign In or Register to comment.