Re: Use CGI to run a Perl script via web server
by haukex (Archbishop) on May 25, 2017 at 11:27 UTC
|
First of all, doing my $sso = $query->param( "sso" ); system( "perl myscript.pl $sso" ); like that in a CGI script is extremely dangerous! - you are allowing anyone to execute any command on your server with this CGI script! To see what I mean, try setting $sso to "; cat /etc/passwd".
I think that any kind of calling of an external command in a CGI script should be used as rarely as possible, if at all, and even when it is used, the commands executed must be very tightly controlled to prevent this kind of security hole.
It is very likely that whatever you are trying to implement with this CGI script can probably be accomplished without calling an external command. If you could explain what you are trying to do overall, we can probably suggest a better solution.
Now, getting to your code. You say that it does not work, but don't explain what that means - How do I post a question effectively? Also, the code you posted does not compile - see Short, Self-Contained, Correct Example. As for debugging CGI scripts, try adding use CGI::Carp qw/fatalsToBrowser/; at the top of your script, and see the CGI Help Guide and Troubleshooting Perl CGI scripts.
As for what might be going wrong, aside from the above, you are calling system, which may generate output, before you finish outputting the header (print "Content-type...). Also, it's better to use $query->header instead of generating it yourself.
Lastly, if you really have a really good reason for executing external commands from a CGI script, I wrote at length about avoiding the shell here. But this is just one of several possible security holes, and by itself will probably still not close all attack possibilities.
| [reply] [d/l] [select] |
Re: Use CGI to run a Perl script via web server
by kcott (Archbishop) on May 25, 2017 at 11:37 UTC
|
#create CGI query object to get the SSO from URL
my $sso = new CGI;
my $sso = $query->param( "sso" );
Should probably be:
#create CGI query object to get the SSO from URL
my $query = new CGI;
my $sso = $query->param( "sso" );
You've used strict which would have aborted your script with:
Global symbol "$query" requires explicit package name (did you forget
+to declare "my $query"?) at ...
That's probably in your web server logs.
Consider using CGI::Carp, while developing, to see these types of messages immediately, with:
use CGI::Carp 'fatalsToBrowser';
You should also turn on warnings.
Had you done so, Perl would have given you more help like this:
"my" variable $sso masks earlier declaration in same scope at ...
| [reply] [d/l] [select] |
Re: Use CGI to run a Perl script via web server
by choroba (Cardinal) on May 25, 2017 at 11:26 UTC
|
What do you mean by "it is not detecting"? Does it run normal system? Does it throw an error? Do you use mod_perl?
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] |
Re: Use CGI to run a Perl script via web server
by ww (Archbishop) on May 25, 2017 at 11:25 UTC
|
The documentation (at http://search.cpan.org/~pjf/IPC-System-Simple-1.25/lib/IPC/System/Simple.pm says, very plainly:
"...use the "capture()" command just like you'd use backticks. If there's an error, it will die with a detailed description of what went wrong."
So, I ask, what's that look like?
Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
- code
- verbatim error and/or warning messages
- a coherent explanation of what "doesn't work actually means.
| [reply] |
|
Thanks everyone for all the comments. First of all, sorry to not mention "doesn't work". There is no security risk as this Link will only be used from within a different application. I am providing the script that needs to be executed over CGI via the webserver. It connects to LDAP and queries the username and some other details and with those creates a user account in another application (using system call). Reason is mentioned in the script comments.
This script works fine with shift flag on line 11, by running the script manually like 'perl myscript.pl 212453261'.
#!/usr/bin/perl
use strict;
use CGI;
use Net::LDAP;
use IPC::System::Simple qw(system capture);
#create CGI query object to get the SSO from URL
#my $query = new CGI;
#my $sso = $query->param( "sso" );
my $sso = shift;
if( $sso == "" )
{
print "<html>";
print "<body>";
print "<h1>\n\n ERROR: Entered SSO is EMPTY! </h1>\n\n";
die "Empty SSO";
}
else
{
print "<p>Processing: $sso</p>\n\n";
#LDAP server with port
my $LDAP_SERVER = 'ldaps://ldap.hostname.com:636/ou=enterprise,dc=vds,
+dc=logon';
my $LDAP_USER = 'bind_user';
my $LDAP_PWD = 'bindpwd';
#base tree to start searching
my $BASE = "ou=users,ou=enterprise,dc=vds,dc=logon";
#Just search for the SSO - no group search required.
my $FILTER = "(cn=$sso)";
#values to return - we need CN - SSO, First Name, Last Name, and Email
my $ATRBS = ['cn', 'givenName', 'sn', 'mail'];
#Start LDAP session and bind to LDAP
my $ldap = Net::LDAP->new($LDAP_SERVER) or die "$@";
my $mesg = $ldap->bind($LDAP_USER, password=>$LDAP_PWD);
my $result = $ldap->search(base => $BASE,
filter => $FILTER,
attrs => $ATRBS
);
my @entries = $result->entries;
#only one result should be returned
if(@entries == 1) {
print "\n\t<p>Found user $sso in LDAP</p>\n";
my $usr = $entries[0];
my $firstName = $usr->get_value('givenName');
my $lastName = $usr->get_value('sn');
my $email = $usr->get_value('mail');
print "\t<p>Creating User account in Application with \n
Login name:- $sso \n
FullName:- $firstName $lastName \n
Email ID:- $email \n
</p>\n\n";
#*********SYSTEM CALL **********
#script within a script both files in same path
#This is required because the main script runs with ActiveState Extend
+ed Perl v5.24.1
#Whereas cqperl runs with v5.16.1 (limited features), cannot use Activ
+eState for this one.
#*********SYSTEM CALL **********
system( "cqperl NewLdapUser.pl $sso $firstName $lastName $email" );
print "\n\t<p>Application account created for $sso - $firstName $last
+Name - $email</p>\n\n";
}
else {
#error
print "\t<h1>ERROR: Wrong SSO or User doesn't exist in OneAD LDAP</h
+1>\n\n";
}
$mesg = $ldap->unbind;
}
print "\t<h3>DONE!</h3>\n";
print "</body></html>";
The output of the script is attached below. All I am looking for is to find out a way to parse the value from $sso = shift to just $sso using CGI.
# perl myscript.pl 212453261
<p>Processing: 212453261</p>
<p>Found user 212453261 in LDAP</p>
<p>Creating User account in Application with
Login name:- 212453261
FullName:- John Doe
Email ID:- john.doe@mailhost.com
</p>
<p>Application account created for 212453261 - John Doe - john
+.doe@mailhost.com</p>
<h3>DONE!</h3>
| [reply] [d/l] [select] |
|
There is no security risk as this Link will only be used from within a different application.
The road to Pwnsville (and thence to Bankruptcy) is littered with the corpses of devs who said precisely that.
Use taint mode. Use it right now. Secure your code. Then secure it some more. Try to break it. Have others try to break it. Write security tests. Become known as the one in your team who writes the bulletproof code. Teach others what you have learned.
| [reply] |
|
There is no security risk as this Link will only be used from within a different application.
Sorry, but those are famous last words. Getting security right is really hard. At the very least, you need to use the LIST form of system, i.e. system("cqperl","NewLdapUser.pl",$sso,$firstName,$lastName,$email);, and even better, since you're already using IPC::System::Simple, be explicit by using its systemx instead of system function. <update2> Plus, what hippo said, plus some kind of authentication for this script, and so on. </update2>
... creates a user account in another application (using system call). Reason is mentioned in the script comments.
I admit I don't know cqperl (ClearQuest Perl?), but I'm not entirely convinced that whatever the Perl script NewLdapUser.pl is doing could not be done by your CGI script, especially given that your script is already making use of Net::LDAP.
$sso == ""
This is not doing what you want, as Perl would tell you, that's why you should always Use strict and warnings. Use eq instead and see the Basic debugging checklist.
All I am looking for is to find out a way to parse the value from $sso = shift to just $sso using CGI.
I'm not sure I understand the question, are you having trouble with getting the CGI parameters? I don't really see anything immediately wrong with my $sso = $query->param("sso");, have you tried narrowing down your script to only that part and attempting to debug it (using the links previously provided)?
Update: Your code also seems to be potentially vulnerable to a Cross-site scripting (XSS) attack, see also this. Even if not, you should still use CGI's escapeHTML() function.
| [reply] [d/l] [select] |
|
|
|
|
|
When accepting a parameter, you will need to know how the other side sends the parameter.
If your other side sends the parameter as a CGI parameter, like:
http://example.com/cgi-bin/myscript.pl?sso=212453261
then you can read that parameter using the CGI methods:
my $sso = $query->param('sso');
$sso = 0+ $sso; # convert to number, strip all leading zeroes
But note that the "current directory" may not be what you think it is. When running other programs, you should use the full path to them and all filenames:
#*********SYSTEM CALL **********
#script within a script both files in same path
#This is required because the main script runs with ActiveState Extend
+ed Perl v5.24.1
#Whereas cqperl runs with v5.16.1 (limited features), cannot use Activ
+eState for this one.
#*********SYSTEM CALL **********
system( "c:\\path\\to\\cqperl C:\\another\\path\\to\\NewLdapUser.pl $
+sso $firstName $lastName $email" );
| [reply] [d/l] [select] |
Re: Use CGI to run a Perl script via web server
by Anonymous Monk on May 25, 2017 at 11:20 UTC
|
| [reply] |