Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re^2: Debugging cgi-bin script

by walkingthecow (Friar)
on Jan 06, 2013 at 01:29 UTC ( #1011820=note: print w/ replies, xml ) Need Help??


in reply to Re: Debugging cgi-bin script
in thread Debugging cgi-bin script

Here's the full code:

#!/usr/local/perl5/bin/perl use strict; use diagnostics; $|++; $ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/ +sbin"; use CGI qw(:all delete_all escapeHTML); if (my $session = param('session')) { # returning to pick up session d +ata my $cache = get_cache_handle(); my $data = $cache->get($session); unless ($data and ref $data eq "ARRAY") { # something is wrong show_form(); exit 0; } print header; print start_html(-title => "Traceroute Results", ($data->[0] ? () : (-head => ["<meta http-equiv=refresh content=5>"])) +); print h1("Traceroute Results"); print pre(escapeHTML($data->[1])); print p(i("... working ...")) unless $data->[0]; print end_html; } elsif (my $host = param('host')) { # returning to select host if ($host =~ /^([a-zA-Z0-9.\-]{1,100})\z/) { # create a session $host = $1; # untainted now print h1("Yes"); my $session = get_session_id(); my $cache = get_cache_handle(); $cache->set($session, [0, ""]); # no data yet if (my $pid = fork) { # parent does delete_all(); # clear parameters param('session', $session); print redirect(self_url()); } elsif (defined $pid) { # child does close STDOUT; # so parent can go on unless (open F, "-|") { open STDERR, ">&=1"; exec "/usr/sbin/traceroute", $host; die "Cannot execute traceroute: $!"; } my $buf = ""; while (<F>) { $buf .= $_; $cache->set($session, [0, $buf]); } $cache->set($session, [1, $buf]); exit 0; } else { die "Cannot fork: $!"; } } else { show_form(); } } else { # display form show_form(); } exit 0; sub show_form { print header, start_html("Traceroute"), h1("Traceroute"); print start_form; print submit('traceroute to this host:'), " ", textfield('host'); print end_form, end_html; } sub get_cache_handle { require Cache::FileCache; Cache::FileCache->new ({ namespace => 'traceroute', username => 'nobody', default_expires_in => '30 minutes', auto_purge_interval => '4 hours', }); } sub get_session_id { require Digest::MD5; Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().$$)); }


Comment on Re^2: Debugging cgi-bin script
Download Code
Replies are listed 'Best First'.
Re^3: Debugging cgi-bin script
by quester (Vicar) on Jan 06, 2013 at 08:21 UTC

    This may be a bit off topic, but...

    Designing your own random number generator in a high-level language is a terrible, terrible idea. There just isn't any way for a normal process to get access to as much entropy as the operating system can gather from timing I/O completions.

    How many bits of entropy are actually in the return from get_session_id? Let's add it up: essentially nothing from the call to time() (because the attacker knows what time it is), about 13 bits from the memory address from {} (estimated on perl 5.14.3 on Linux 3.6), 32 bits from the call to rand() (because an strace shows that perl seeded it by reading four bytes from /dev/urandom), and 15 bits at most from $$ (unless you change /proc/sys/kernel/pid_max and start a lot of processes on your system).

    That's at most 60 bits of randomness that get_session_id tries to magically inflate into 128 bits by calling Digest::MD5::md5_hex a second time. Whatever the second call was intended to do, it's not going to be able to do it.

    Both Solaris and RHEL have had /dev/urandom for a long time; it became standard in Solaris 9 in 2002 and was available as a patch since 2.6 in 1997. It's been standard in every release of RHEL, and was in the old pre-RHEL Red Hat since 4.0 in 1996.

    To make sure your /dev/urandom is working, try

    od -x /dev/urandom | head

    To use it in your script, try this:

    sub get_session_id { require Digest::MD5; open my $ur, "<", "/dev/urandom" or die "Cannot open /dev/urandom, $!"; my $buflen = sysread( $ur, my $buf, 16 ); defined $buflen or die "Failed to read /dev/urandom, $!"; $buflen == 16 or die "Tried to read 16 bytes from /dev/urandom but got $bufl +en"; Digest::MD5::md5_hex( $buf ); }

    Incidentally, never use /dev/random instead of /dev/urandom in this application. For a web server, it exposes the server to a denial-of-service attack where the attacker removes entropy from the system-wide pool, by starting new sessions, faster than entropy is added to the pool, by (mostly) I/O completions.

      Designing your own random number generator in a high-level language is a terrible, terrible idea.

      :) FWIW, merlyn didn't design it, he copied from the fallback Apache::Session::Generate::MD5

      I don't know from entrophy and randomness, but this isn't encryption we're dealing with, no authentication or authorization, no financial transactions -- if the attacker has access to the application, guessing doesn't get him anything he didn't already have access to

      You might like Re^3: Randomness encountered with CGI Session where afoken talks bits

      FYI/FMI Session::Token - Portable, secure, efficient, simple random session token generation that satisfies those OWASP recommendations

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1011820]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (11)
As of 2015-07-28 09:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (254 votes), past polls