Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

CGI and Traceroute

by Anonymous Monk
on Oct 19, 2000 at 03:19 UTC ( [id://37442]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks!
This has been done before but I am trying to write my own CGI/Traceroute program so I can become enlightened.

The below code works but it is not secure- someone can type 127.0.0.1 | cat /etc/passwd and grab my password file!
Ack!
If I uncomment the line below the code doesn't work:
$value =~ s /|/ /g;
Any ideas on what I need to do so the code is totally secure and works?
Thanks!!
#!/usr/bin/perl -w use CGI; my $query = new CGI; $value = $query->param('trace'); #$value =~ s (/;#!"'`|)/ /g; $value =~ s /;/ /g; $value =~ s /#/ /g; $value =~ s /!/ /g; $value =~ s /"/ /g; $value =~ s /'/ /g; $value =~ s /`/ /g; #$value =~ s /|/ /g; open (TRACE, "traceroute $value |"); @traceroute = <TRACE>; close (TRACE); print "Content-Type: text/html\n\n"; print "<html>\n<head>\n<title>\nRavenGate TraceRoute Results\n</title> +\n</head>\n<body>\n"; print "Hello There- I am writing this from scratch so please be patien +t. Thanks!\n\n"; foreach $item (@traceroute) { print "<BR>$item\n\n"; } print "</body>\n</html>\n"; exit (0);

Replies are listed 'Best First'.
Re: CGI and Traceroute
by AgentM (Curate) on Oct 19, 2000 at 03:32 UTC
    Ensure that you are using taint checking: #!/.../perl -wT. Perl will alert you if inputed variables (tainted variables) are used in calls to your piped open or system() and die. You shouldn't be deleting various chars from the string. Do this instead: if it doesn't look like an IP address or hostname, refuse to process it. So the string should contain periods and valid upper and lowercase latin-1 chars ONLY. You can use the m// directive to determine if this is the case.

    I seem to see this all too often. Input is filtered against a few regexes and assumed safe for processing. the true solution to security involves refusing input that doesn't match a criterion and that's IT. In attempt for userfriendliness, it is sometimes attempted to work around this as i see above but this can and will result in security holes that you really can't afford. So again, one filter- pass/fail.

    AgentM Systems nor Nasca Enterprises nor Bone::Easy is responsible for the comments made by AgentM.
Re: CGI and Traceroute
by Kanji (Parson) on Oct 19, 2000 at 06:24 UTC

    Lots of good advice, but I'm surprised no one mentioned avoiding the shell entirely by using the multi-argument forms of system() or exec() to call traceroute directly.

    Put together with the above advice and some sugar, you get something like ...

    #!/usr/bin/perl -wT $|++; use strict; use CGI qw( header start_html end_html param p ); print header, start_html( "RavenGate TraceRoute Results" ); if ( param('trace') and param('trace') =~ /^[-.0-9a-zA-Z]+$/ ) { print p( "Hello There- I am writing this from " . "scratch so please be patient. Thanks!" ), "<pre>"; system( "/usr/sbin/traceroute", param('trace') ); print "</pre>"; print p( "Oops, there was a problem running traceroute" ) if $?; } elsif ( param('trace') ) { print p( "Oops,", param('trace'), "contains illegal characters" ); } else { print p( "Oops, you forgot to give me a host to trace to." ); }

    As for that one line that "doesn't work", you need to escape the pipe (ie, $value =~ s /\|/ /g;).

      ... if ( param('trace') and param('trace') =~ /^[-.0-9a-zA-Z]+$/ ) { print p( "Hello There- I am writing this from " . "scratch so please be patient. Thanks!" ), "<pre>"; system( "/usr/sbin/traceroute", param('trace') ); ...
      Hoo boy. Watch out. You've used param() in both a scalar and a list context. In your security test, you look for things of interest, but in a scalar context, which means you are testing the first param value for trace if multiple values are defined. But then, you suck down all the param-values for trace when you fire off the traceroute. Guess what? You are now passing untested data to traceroute!

      And given that there were some buffer overflow problems with traceroute if I recall my BUGTRAQ listings, giving root access to local users, you've just handed the keys to the kingdom to all-comers. Whee!

      Security - it's not just for breakfast any more.

      -- Randal L. Schwartz, Perl hacker

        Would this be a better approach?

        Update: corrected the code (thanks merlyn); sorry for the delay...

        # assuming -T ... my $param_cmd = param( 'trace' ); if ( $param_cmd ) and ( $param_cmd =~ /^[-.0-9a-zA-Z]+$/ ) { $param_cmd = $1; print p( "Hello There- I am writing this from " . "scratch so please be patient. Thanks!" ), "<pre>"; system( "/usr/sbin/traceroute", $param_cmd ); ... }

        (Sorry it this seems basic, but I'm trying to make sure I've learned the right things from the various FAQ's and nodes on the subject...)

RE: CGI and Traceroute
by redcloud (Parson) on Oct 19, 2000 at 03:29 UTC
    Instead of using s/// to filter out the characters you don't want, use it to only allow the characters you do want.

    How about something like: $value =~ m/([-.0-9a-zA-Z]+)/; $value = $1; That would only allow dashes, dots, and alphanumerics, which IIRC are all you are allowed to use in a fully-qualified domain name.

Re: CGI and Traceroute
by cianoz (Friar) on Oct 19, 2000 at 03:29 UTC
    suppose you accept only ip addresses:
    (changing for hostnames should be trivial..)
    why not just
    unless($value =~/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { ##reject this... }
Re: CGI and Traceroute
by blogan (Monk) on Oct 19, 2000 at 06:20 UTC
    if ($value =~ /\/|;|#|!|"|'|`|\|)/) { print "Invalid parameter"; # perhaps log this "malicious" attempt } else { processhappily(); }
    Don't forget to escape those characters with a \. I usually escape all my non-alphanumerics with a \ because I can't remember which ones are special in regexs (I have my O'Reilly book in front of my now, they're \ | ( ) [ { ^ $ * + ? . but I usually play it safe. Also, but the O'Reilly book if you're new. It's great help

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://37442]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2024-04-24 23:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found