Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

DBI & CGI Security

by sunadmn (Curate)
on Jun 03, 2004 at 15:50 UTC ( #360220=perlquestion: print w/replies, xml ) Need Help??

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

Good day fellow Monks I have a task that has been placed on my shoulders and have some concerns as to how to handle the task.
I have been asked by my company to build a DNS webpage for management of all our RFC1918 space. I have the basic idea of what to do but am looking for some advise on security and overhead. What I have in place now is a pretty simple MySQL DB housing all my DNS data, thanks to the help of Limbic~Region and many other monks. Now the general idea is to have a secure site where given users log into the site and can mangae certain things, I would love to handle privliges on a user level here but that can come later. I have set out searching CPAN for mods that might be able to help me out and it is obvious I will have to use DBI to manipulate the DB, but here is where I come into a security question and have not found the answer in the O'Reily DBI book yet. Security question is can I do some sort of include to include the auth info for the DB server so I do not have that in my main CGI? I know this may sound trivial to some, but I have not been able to find a good answer and am still a newbie to perl.

Secondly my main concern is overhead since this will run on a small Sun Netra T1 and will have many users loggin in at the same time. My idea for sanity checking is to load the PTR and A record tables into an array for given domain name and then use Array::Compare to test for the data set in both, but was concerned about hoggin down the server if multiple users run a query at the same time. I am really just trying to get some pointers as to how to build a more efficent server/app any pointers you may offer would be great.


Replies are listed 'Best First'.
Re: DBI & CGI Security
by samtregar (Abbot) on Jun 03, 2004 at 16:19 UTC
    Security question is can I do some sort of include to include the auth info for the DB server so I do not have that in my main CGI?

    I suggest you pick up a good on CGI programming in Perl, like O'Reilly's CGI Progamming with Perl. Any good CGI book will cover building a simple login system. Once you see how it's done adapting it to "include the auth info for the DB server" (whatever that means) shouldn't be hard.

    My idea for sanity checking is to load the PTR and A record tables into an array for given domain name and then use Array::Compare to test for the data set in both

    I don't know much about your application, but this sounds like a really poor idea. You should find a way to express this check as one or more SQL statements which will let MySQL do the heavy lifting for you. With the proper indexes I'm sure MySQL can beat Array::Compare.


      Well the auth on the server side is not a real issue I can hendle that via .htaccess but the security I was and am looking for is more or less for the DBI connect I want to hide that so as to take more of the risk out the DB being compromised, Does that make more sense?

        What kind of attack are you trying to prevent? Are you trying to make it so that an attacker could get into the web server but not be able to get into the database? That's an unusual requirement...

        I'm not sure what the best way to do it would be. Maybe encrypt the DB password and store it on disk. Then require the admin to enter the decryption password whenever the server is started. The server would load the decrypted password into memory and use it to connect to the DB. It's still vulnerable to a root compromise since the plaintext password will exist in memory, but it would keep the password unreadable on disk. You'd still be vulnerable to key-loggers and the like, of course.

        Ultimately it's hard to create a system that can do a given job but won't let an attacker do the same job if they break in.


        I assume you don't want the users to supply the password for the DBI connect string, right? If that is the case you could store the password in a file (encrypted with some sort of PKI possibly). Just a suggestion, hopefully some monk will give a better one. Also you might want to poke around the Monastery some more. I've seen this issue discussed before here. I asked a simiular question a while back and got many good suggestions.

        Plankton: 1% Evil, 99% Hot Gas.
        The solution I used on our company's website is to have all the connection done with a module which is outside of the htdocs-tree and hence not easily reachable for web-users.

        Of course (before anyone else says so) if the machine on which your web-server runs is compromised, all bets are off, but then I fear that it is already too late to do much.


        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: DBI & CGI Security
by jZed (Prior) on Jun 03, 2004 at 16:11 UTC
Re: DBI & CGI Security
by jayrom (Pilgrim) on Jun 03, 2004 at 16:47 UTC
    What I do for the DB auth info is put the login and password in a text file outside the web server realm.
    You can open the file from your DB login script and parse it to retrieve the login and password.
    Something like this:

    my $file = '/path/db.txt'; open FILE, '<', $file or die $!; chomp(my ($auth) = <FILE>); my ($dbuser, $dbpasswd) = split('\t', $auth); close FILE;
    Hope this helps.


      I have followed this exact scenario, though I encrypt it with Crypt::CBC. Here's how my code looks:
      my ($username, $keyfile, $domain) = @_; open (PASS, "</home/$username/$keyfile") or die "Error: $!\n"; flock (PASS, 2); my @keypass = <PASS>; close (PASS); foreach (@keypass) { chomp $_; } my $cipher = Crypt::CBC->new($keypass[0], 'Blowfish'); my $dbpass = $cipher->decrypt($keypass[1]); use DBI qw(:sql_types); my $userdatabaseName = "DBI:mysql:$domain"; my $userdatabaseUser = $username; my $userdatabasePw = $dbpass; $dbh = DBI->connect($userdatabaseName, $userdatabaseUser, $userdatabasePw, { RaiseError => 1},) or die "Connect failed: $DBI::er +rstr\n";
      I also recommend the aforementioned O'Reilly's "CGI Progamming with Perl." And take a look at this node on CGI and passwords.

      "A little yeast leavens the whole dough."
        I like the way you used encryption. I also often forget to lock the file when I only read it ;-)

        This may be a silly question, and it doesn't mean to be ironic, but does encryption make a difference?
        Indeed having a text file with the db auth on the server is only slightly better than having it in a script within the web server realm.
        But, if you bear with me, if someone gets access to that file couldn't we assume that they also had access to the script? Also given that the key has to be included somewhere, how hard would it be to figure out the whole thing?
        Should we encrypt the auth by default for the sake of good security practice?


      One note with that code is that you may want to structure it something like this:
      use vars qw[$dbuser $dbpass $dbsecret_time]; my $secretfile = '/path/db.txt'; my $secretfile_modtime = stat($secretfile)[9]; if (!$dbsecret_time or $dbsecret_time < $secretfile_modtime) { open FILE, '<', $file or die $!; chomp(my ($auth) = <FILE>); ($dbuser, $dbpasswd) = split('\t', $auth); close FILE; $dbsecret_time = $secretfile_modtime; }
      The reason is that if you ever want to run this code under mod_perl or something similar, you probably won't want to hit the dbpass/secret file more often than necessary.
      -- @/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://360220]
Approved by mpeppler
Front-paged by arden
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (1)
As of 2021-03-08 04:02 GMT
Find Nodes?
    Voting Booth?
    My favorite kind of desktop background is:

    Results (123 votes). Check out past polls.