http://www.perlmonks.org?node_id=1222158

Aldebaran has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I lurk on threads that are pitched to my aptitude and needs, with Re^3: Sample REST request & response code being a recent one, and in particular thanos's responses. I had a perl sftp capability that was still using the password and knew that better implementations used key pairs. I followed the methods laid out in english instructions to set up ssh on ubuntu as well as almost the same treatment in russian. ssh goes off really slick now:

$ ssh u6121220@home349357426.1and1-data.host The programs included with the Debian GNU/Linux system are free softwa +re; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. (uiserver):u61210220:~$ pwd /kunden/homepages/9/d349357426/htdocs

Where it goes off the rails for me is the ultimate step in the above links. It amounts to changing the PasswordAuthentication line here:

sudo nano /etc/ssh/sshd_config

Nothing I do seems to make me a superuser. su doesn't prompt for password.

(uiserver):u61210220:~/perlmonks/scripts$ su (uiserver):u61210220:~/perlmonks/scripts$ man su (uiserver):u61210220:~/perlmonks/scripts$ sudo anything -bash: sudo: command not found (uiserver):u61210220:~/perlmonks/scripts (uiserver):u61210220:~$ chmod +w /etc/ssh/sshd_config chmod: changing permissions of ‘/etc/ssh/sshd_config’: Read-only file +system$

I was surprised to see that this server is running ubuntu:

(uiserver):u61210220:~$ lsb_release -r -i -c -d Distributor ID: Debian Description: Debian GNU/Linux 8.11 (jessie) Release: 8.11 Codename: jessie (uiserver):u61210220:~$ uname -a Linux infong972 3.16.0-ui18135.21-uiabi1-infong-amd64 #1 SMP Debian 3. +16.56-1~ui80+1 (2018-05-15) x86_64 GNU/Linux (uiserver):u61210220:~$

Q1) Am I right to think that nothing I do will allow me to write to this file? If so, then is my site as vulnerable to an attack with enumerating passwords as ever?

Q2) Can I write a script that lets me know when there are more than 20 tries/hour at a password entrance?

Here is the script that can now employ the key path for sftp:

$ cat 2.sftp1.pl #!/usr/bin/perl -w use 5.011; use Net::SFTP::Foreign; my $upload_file = shift; my $sftp = get_tiny(); my $server_dir = "perlmonks/scripts"; $sftp->mkdir("/$server_dir") or warn "mkdir1 failed $!\n"; $sftp->setcwd("/$server_dir") or warn "setcwd1 failed $!\n"; $sftp->put($upload_file) or warn "upload put failed $!\n"; my $remote_dir = $sftp->cwd; say "remote dir is $remote_dir"; my $ls = $sftp->ls( $remote_dir); print "$_->{filename}\n" for (@$ls); say "final ref to sftp object is is $sftp"; undef $sftp; sub get_tiny { use 5.011; use warnings; use Net::SFTP::Foreign; use Config::Tiny; use Data::Dumper; my $ini_path = qw( /home/bob/Documents/html_template_data/3.values.i +ni ); say "ini path is $ini_path"; my $sub_hash = "my_sftp"; my $Config = Config::Tiny->new; $Config = Config::Tiny->read( $ini_path, 'utf8' ); say Dumper $Config; # -> is optional between brackets my $domain = $Config->{$sub_hash}{'domain'}; my $username = $Config->{$sub_hash}{'username'}; my $password = $Config->{$sub_hash}{'password'}; my $port = $Config->{$sub_hash}{'port'}; my $key_path = $Config->{$sub_hash}{'key_path'}; #dial up the server say "values are $domain $username $password $port $key_path"; my $sftp = Net::SFTP::Foreign->new( $domain, user => $username, port => $port, # password => $password, key_path => $key_path ) or die "Can't connect: $!\n"; return $sftp; } __END__ $

So I can get scripts to my server conveniently but I really don't know what to do once they are there. Q3) Should I constitute a cpan capability, and if so where?:

(uiserver):u61210220:~$ cd perlmonks/scripts (uiserver):u61210220:~/perlmonks/scripts$ ls 1.eclipse.pl 1.hello.pl 1.upload.pl 1.encodings.txt 1.initialize.pl 2.create.bash (uiserver):u61210220:~/perlmonks/scripts$ ./1.upload.pl Can't locate CGI/Lite.pm in @INC (you may need to install the CGI::Lit +e module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/p +erl/5.20.2 /usr/local/share/perl/5.20.2 /usr/lib/x86_64-linux-gnu/per +l5/5.20 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.20 /usr/sha +re/perl/5.20 /usr/local/lib/site_perl .) at ./1.upload.pl line 8. BEGIN failed--compilation aborted at ./1.upload.pl line 8. (uiserver):u61210220:~/perlmonks/scripts$

Thank you for your comment,

Replies are listed 'Best First'.
Re: using perl on server side for secure connections
by thanos1983 (Parson) on Sep 12, 2018 at 08:54 UTC

    Hello Aldebaran,

    Regarding your Q1:

    First solution is to ssh as root. You initially need to set ssh-keys as root the same way you did as normal user. For example ($ ssh-copy-id -p 22 <root@hostname or IP>).

    On the next step assuming you are root you can modify the file. Alternative solution:

    $ ssh -p 22 localhost Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.15.0-33-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage 2 packages can be updated. 0 updates are security updates. New release '18.04.1 LTS' available. Run 'do-release-upgrade' to upgrade to it. *** System restart required *** You have new mail. Last login: Wed Sep 12 10:40:51 2018 from 127.0.0.1 user@hostname:~$ sudo su - [sudo] password for user: root@hostname:~#

    Update2: I also found (I was not aware) that you might be missing the sudo package. Follow the information on how to install it from here -bash: sudo: command not found.

    Regarding Q2 you are referring probably to Limit failed logins to SSH. You can collect the data from the attempts at $ less /var/log/auth.log for Ubuntu servers. If you want to make the server more secure from this type of attacks I would recommend to follow this article Stop SSH brute force attempts. At this point you can have a script checking regularly the file and you can set a condition and in case that something matches your condition, make your script to email you and notify you regarding the attack or to check the file etc... etc...

    Update: These are a few lines from my server:

    Sep 10 17:39:01 user CRON[28734]: pam_unix(cron:session): session open +ed for user root by (uid=0) Sep 10 17:39:01 user CRON[28734]: pam_unix(cron:session): session clos +ed for user root Sep 10 17:42:31 user sudo: pam_unix(sudo:auth): auth could not identif +y password for [user]

    You need to set your own conditions.

    Regarding Q3 I do not think that you need CPAN module to do that for you, based on the above information I assume that you can resolve your problems. reading again your question I have not really addressed it. What is the goal once you upload the files to the server? Do you want to execute them, do you want to do something else? We need more information on this.

    Unfortunately my answer is not Perl code related but general information regarding ssh and LinuxOS but I think this should cover your question.

    If I misunderstood your questions or I have missed a point please let me know and I will try to reply as soon as possible.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

      Thank you thanos for your detailed response. It takes me some time to work through the issues involved. I tried to get through on ssh as root, but I didn't seem to have the necessary values, nor was I allowed to make many attempts. It occurs to me now that I *couldn't* have the values necessary, as I'm just a guy who rents hosting services on 1and1. If all you needed to do was buy the lowest amount of webhosting they offer and have access to the whole enchilada, nothing would be secure.

      I'm living a bit of different life to not have root priveleges. Many commands aren't available, such as passwd, but I realized that I was likely not going to be able to change /etc/ssh/sshd_config. If I did, I believe it might hold for all of the clients on that server. (yes/no)? I didn't fail for lack of attempts that usually do something for me in a new environment. Since they have more to do with unix than perl, I omit them. It would seem that ftp'ing is among the few tricks I can pull off with the filesystem they provide:

      (uiserver):u61210220:/kunden/homepages/9/d349337426$ groups ftpusers

      What hit paydirt was the old, reliable

      (uiserver):u61210220:~$ perl -MCPAN -e shell

      The dialog confirmed what seemed manifest:

      Warning: You do not have write permission for Perl library directories +. What approach do you want? (Choose 'local::lib', 'sudo' or 'manual') [local::lib]

      In one attempt, I selected 'sudo' but it was a quick dead end. What did work was making a local::lib in a place where I have write privileges. After autoconfiguration, I was left with values that needed to be added to the shell environment for any of this to work. They seem not to be persistent, so I wrapped these 4 commands in a little bash script, which I'll show between readmore tags with the new envelope variables.

      Q4) Is there a more perl way to do this?

      The good news is that I have a script that can find the necessary modules. I am attempting to run an upload script for the server side, which I found by lurking on a node a few weeks back. I get an error that a file does not exist, but I do have a /home/bob/1.scripts/8.nik.pl on my local machine.

      -------executing 1.upload.sh Can't open /home/bob/1.scripts/8.nik.pl: No such file or directory at +/kunden/homepages/9/d349337426/htdocs/perl5/lib/perl5/CGI/Lite.pm lin +e 862. Use of uninitialized value $readme in concatenation (.) or string at 1 +.upload.pl line 79. Use of uninitialized value $readme in <HANDLE> at 1.upload.pl line 87. readline() on unopened filehandle at 1.upload.pl line 87. -------cat 1.upload.pl #!/usr/bin/perl # Simple example that displays the data associated with # the "readme" file field in a multiform/form-data request. use strict; use warnings; use CGI::Lite; my $cgi = CGI::Lite->new; # Die if the directory is invalid (i.e doesn't exist, can't # read or write to it, or is not a directory). $cgi->set_directory ("/tmp") or die "Directory doesn't exist.\n"; # Set the platform. "Unix" is the default. The method accepts # platforms in a case insensitive manner, so you can pass # "UNIX", "Unix", "unix", etc. $cgi->set_platform ("Unix"); # Set the buffer size to 1024 bytes (1K). This is the default. $cgi->set_buffer_size (1024); # Let's change the way uploaded files are named! $cgi->filter_filename (\&my_way); # Tell the module to return filehandles. $cgi->set_file_type ('handle'); # We want CGI::Lite to perform EOL conversion for all files that have +the # following MIME types: # # application/mac-binhex40 # application/binhex-40 # # so, we use the add_mime_type method. In addition, we don't want # files of MIME type: text/html to be converted. I'm sure you wouldn't # want to do that in real life :-) $cgi->add_mime_type ('application/mac-binhex40'); $cgi->add_mime_type ('application/binhex-40'); $cgi->remove_mime_type ('text/html'); # Let's go ahead and parse the data! my $data = $cgi->parse_form_data; print "Content-type: text/plain", "\n\n"; if ($cgi->is_error) { my $error_message = $cgi->get_error_message; print <<End_of_Error; Oops! An error occurred while uploading the file. Please go back and try to upload the file again. In the meanwhile, you may want to report the following error to the Webmaster: $error_message Sorry, and thanks for being patient! End_of_Error } else { # Dereferences the variable to get a filehandle. Then, # iterates through the file, displaying each line to STDOUT. # # NOTE: $readme also contains the name of the file. my $readme = $data->{readme}; print <<End_of_Header; Thanks for uploading the file: $readme to our server. Just in case you're interested, here are the contents of your uploaded file: End_of_Header while (<$readme>) { print; } # Make sure to close the file! $cgi->close_all_files; } exit (0); sub my_way { my $file = shift; $file =~ tr/A-Z/a-z/; # Upper to lowercase $file =~ s/(?:%20)+/_/g; # One or more spaces to "_" $file =~ s/%[\da-fA-F]{2}//g; # Remove all %xx return ($file); }

      I have never executed a CGI script before so I don't know if this is a perfectly good script that I don't know how to work. Currently, the line that draws the error is

      while (<$readme>) {

      Q5) Given that ~/perlmonks/scripts/uploads is where I want files to land, what perl script will get them there?

        I have never executed a CGI script before so I don't know if this is a perfectly good script that I don't know how to work.

        CGI is a protocol for exchange of data between client and server over HTTP (that's a simplification). The important part here is the "over HTTP" bit. If you are intending to run this script over the web then you'll most likely want to construct a form (which may be static) to go with this script which will then be the form handler. There's more about CGI in the Tutorials section.

        Conversely, if you are not intending to use a script like this over HTTP then it would be better and simpler not to use CGI in the first place.

        It's not immediately clear to me from reading this thread what your ultimate goal is.