How to detect XSS Reflect with Perl - perl

I created this simple script to request a URL with a JavaScript payload.
#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request;
use LWP::Simple;
my $req=HTTP::Request->new(GET=>"http://example.com.br/search.asp?CI=%27%3E%3Cscript%3Ealert('XSS')%3C/script%3E");
my $ua=LWP::UserAgent->new();
$ua->timeout(15);
my $res=$ua->request($req);
print $res->content;
How can I identify if there is an XSS vulnerability in this example?

To quickly answer how it could work for your particular example:
#!/usr/bin/perl
use strict;
my $url = "http://example.com.br/search.asp?CI=%27%3E%3Cscript%3Ealert('XSS')%3C/script%3E";
#### decode url-encoding
my $decoded_url = $url=~s/%([A-F\d]{2})/chr(hex($1))/iegr;
if ( $decoded_url=~/<script>.*<\/script>/ ) {
print "XSS detected: $& \n";
}
You'd get:
$ ./xssdetect.pl
XSS detected: <script>alert('XSS')</script>
Caveat: This alone is no XSS protection of real-world use. XSS is a complicated topic with lots of irregularities and special rules. I suggest reading up on XSS, for example at OWASP.

Related

Perl: CGI redirect from multiple submit buttons

I have a small CGI Script with 2 submit buttons. I want that the current Script redirects the User to another script, depending on which submit button is pressed.
The CGi-Script:
#!/usr/bin/perl -w
# Modules
use strict;
use warnings;
use CGI;
my $q = CGI->new();
print $q->header();
print $q->submit(-name=>'button',-value => 'disable');
print $q->submit(-name=>'button',-value => 'enable');
if ($q->param('button') eq "disable"){
print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?disable");
} elsf ($q->param('button') eq "enable"){
print $q->redirect(-uri=>"http://1.1.1.1./cgi-bin/services/switch_XXX.cgi?enable");
} else {
}
But none of the actions is actually performed. The Error-Log shows the following:
[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 23.
[Tue Mar 06 11:48:44 2018] [error] [client XXXX] Use of uninitialized value in string eq at /var/www/cgi-bin/test.cgi line 26.
Could someone of you tell me what causes the error and why the redirect is not working?
Many thanks in advance!
See "Generating a redirection header" in the CGI docs: "If you use redirection like this, you should not print out a header as well."
The messages you're seeing in the log are referring to the $q->param('button') eq "disable" checks: $q->param('button') is returning undef because the field has not been submitted yet, so you're comparing "disable" to the undefined value. These are warning messages only, that you can avoid by first checking if $q->param('button') has a true value before doing the eq comparison. (Note: In other cases, one might want to use defined to check for undef, because there are some values in Perl that are defined but still false, see Truth and Falsehood - but in this case, both "disable" and "enable" are true values.)
Also, your submit buttons need to be in a <form>. And note you've got a typo with elsf. This works for me:
#!/usr/bin/env perl
use strict;
use warnings;
use CGI;
my $q = CGI->new();
if ( $q->param('button') && $q->param('button') eq "disable" ) {
print $q->redirect(-uri=>"...");
} elsif ( $q->param('button') && $q->param('button') eq "enable" ) {
print $q->redirect(-uri=>"...");
} else {
print $q->header();
print $q->start_html;
print $q->start_form;
print $q->submit(-name=>'button', -value=>'disable');
print $q->submit(-name=>'button', -value=>'enable');
print $q->end_form;
print $q->end_html;
}
If you are just starting to write web applications in Perl, I would urge you to read CGI::Alternatives and decide whether you really want to use such old technology when newer and better (and still Perl-based) alternatives are available.
However, if you decide to stick with CGI (and CGI.pm) then there are a couple of things that can make your life easier.
It's a rare CGI program that needs two CGI objects
For most CGI programs, using an object-oriented approach is overkill. You rarely need objects. CGI.pm has a, simpler, function-based approach that you can use instead. Simply, import the functions that you want to use as you load the module:
use CGI qw[param header redirect];
Then use them without creating an object first:
if (param) {
print redirect(...);
} else {
print header(...);
}
The CGI-Generation functions are a terrible idea
It's even in the documentation.
HTML Generation functions should no longer be used
All HTML generation
functions within CGI.pm are no longer being maintained. Any issues,
bugs, or patches will be rejected unless they relate to fundamentally
broken page rendering.
The rationale for this is that the HTML generation functions of CGI.pm
are an obfuscation at best and a maintenance nightmare at worst. You
should be using a template engine for better separation of concerns.
See CGI::Alternatives for an example of using CGI.pm with the
Template::Toolkit module.
These functions, and perldoc for them, are considered deprecated, they
are no longer being maintained and no fixes or features for them will
be accepted. They will, however, continue to exist in CGI.pm without
any deprecation warnings ("soft" deprecation) so you can continue to
use them if you really want to. All documentation for these functions
has been moved to CGI::HTML::Functions.
Putting your HTML into an external template is a much better idea. And it will be easier for your front-end developer to edit. Yes, I realise you probably don't have a front-end developer on your project right now - but don't you want to plan ahead?
Having said that, your program becomes something like this:
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw[param header redirect];
my $disable_url = '...';
my $enable_url = '...';
if (param('button') {
if (param('button') eq 'disable') {
print redirect($disable_url);
} elsif (param('button') eq 'enable') {
print redirect($enable_url);
}
exit;
}
print header;
print $some_output_that_is_generated_from_a_template.

Perl LWP::Simple won't GET some URLs

I am trying to write a basic webscraping program in Perl. For some reason it is not working correctly and I don't have the slightest clue as to why.
Just the first part of my code where I am getting the content (just saving all of the HTML code from the webpage to a variable) does not work with certain websites.
I am testing it by just printing it out, and it does not print anything out with this specific website. It works with some other sites, but not all.
Is there another way of doing this that will work?
#use strict;
use LWP::Simple qw/get/;
use LWP::Simple qw/getstore/;
## Grab a Web page, and throw the content in a Perl variable.
my $content = get("https://jobscout.lhh.com/Portal/Page/ResumeProfile.aspx?Mode=View&ResumeId=53650");
print $content;
You have a badly-written web site there. The request times out with a 500 Internal Server Error.
I can't suggest how to get around it, but the site almost certainly uses JavaScript as well which LWP doesn't support, so I doubt if an answer would be much use to you.
Update
It looks like the site has been written so that it goes crazy if there is no Accept-Language header in the request.
The full LWP::UserAgent module is necessary to set it up, like this
use strict;
use warnings;
use LWP;
my $ua = LWP::UserAgent->new(timeout => 10);
my $url = 'https://jobscout.lhh.com/Portal/Page/ResumeProfile.aspx?Mode=View&ResumeId=53650';
my $resp = $ua->get($url, accept_language => 'en-gb,en', );
print $resp->status_line, "\n\n";
print $resp->decoded_content;
This returns with a status of 200 OK and some HTML.
To interact with a website that uses Javascript, I would advise that you use the following module:WWW::Mechanize::Firefox
use strict;
use warnings;
use WWW::Mechanize::Firefox;
my $url = "https://jobscout.lhh.com/Portal/Page/ResumeProfile.aspx?Mode=View&ResumeId=53650"
my $mech = WWW::Mechanize::Firefox->new();
$mech->get($url);
print $mech->status();
my $content = $mech->content();

Perl CGI get user's user-agent

I have Perl CGI pages, (.pl extension). How Can I get a persons raw user agent string? There are ways of doing it in Javascript, (which I have been), though I'd rather move over to completely Perl, rather then having some Javascript and some Perl.
In example, to get a person's IP: $ENV{REMOTE_ADDR}
User agent is stored in $ENV{HTTP_USER_AGENT}
Use the CGI module:
#!/usr/bin/perl -wT
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
print header;
print start_html("Environment");
foreach my $key (sort(keys(%ENV))) {
print "$key = $ENV{$key}<br>\n";
}
print end_html;
As people have already mentioned, it's always available in the $ENV{HTTP_USER_AGENT} variable. But if you're using CGI.pm, you can also get it by calling the user_agent() function.

using perl cgi to fetch cookies

I'm trying to inspect cookie values in a cgi script; my test script looks like
#!/usr/bin/perl -w
use DBI;
use CGI qw/:standard/;
use CGI::Cookie;
my $cgiH = CGI->new;
print header;
print start_html(-title=>'Cookie Terms'), h1("Cookie Terms"), "<hr>\n";
%cookies = CGI::Cookie->fetch;
foreach $k (keys %cookies) {
my $term = "$cookies{$k}";
my $term =~ s/SubjectTerm//;
print "at $k is $term \n";
}
print end_html;
the relevant input to the script (from an HTTP GET) is
Cookie: SubjectTerm1=ponies
Cookie: SubjectTerm2=horses
(this is verified by using either fiddler or debugging the code in my delphi app). the result of my script (omitting the HTML wrapper) is either
at SubjectTerm1 is
at SubjectTerm2 is
or if I change the print statement to
print "at $k is $cookies{$k}\n";
it is
at SubjectTerm1 is SubjectTerm1=ponies; path=/
at SubjectTerm2 is SubjectTerm2=horses; path=/
What I want to arrive it is something like this
at SubjectTerm1 is ponies
at SubjectTerm2 is horses
I know I'm missing something about the hash usage but can't quite figure out what it is.
am I not addressing the %cookies hash correctly?
If you had use warnings you would see you are clobbering the $term with the line
my $term =~ s/SubjectTerm//;
Remove the my.
I think you might be able to extract the value is simply changing the assignment to
my $term = $cookies{$k}->value();
and get rid of the s/SubjectTerm//. But not sure about this sorry.
As an aside, before I answer the question, I'd strongly recommend you look at using something other than CGI.pm -- it's the best of late-90s Perl, and other than being included by default in the core perl distribution has little to recommend it.
Some more modern, more featureful alternatives include:
CGI::Application - http://cgi-app.org/
Mojolicious - http://mojolicio.us/
Dancer - http://www.perldancer.org/
Beyond that, as #Sodved says if you'd included use strict; and use warnings; at the top of your file the first of your problems -- clobbering $term by using my twice -- would have been highlighted immediately.
Once you're using the strict and warnings pragmas (and I'd say, don't leave home without them) you'll also want to change your foreach to either:
foreach (keys %cookies) {
my $term = $cookies{$_};
...
OR
foreach my $k (keys %cookies) {
my $term = $cookies{$k};
...
That is, you'll either need to declare the $k variable, or you may prefer to use Perl's built-in $_ inside the loop -- it's purely a matter of style.
Good luck!

Decoding URI related entities with Perl

I may not even be referring to this the proper way so my apologies in advance. Our server logs are constantly showing us an encoded style of attack. An example is below....
http://somecompany.com/script.pl?var=%20%D1%EB........ (etc etc)
I am familiar with encoding and decoding HTML entities using Perl (using HTML::Entities) but I am not even sure how to refer to this style of decoding. I'd love to be able to write a script to decode these URI encodings (?). Is there a module that anyone knows of that can point me in the right direction?
Nikki
Use the URI::Escape module to escape and unescape URI-encoded strings.
Example:
use strict;
use warnings;
use URI::Escape;
my $uri = "http://somecompany.com/script.pl?var=%20%D1%EB";
my $decoded = uri_unescape( $uri );
print $decoded, "\n";
There are online resources such as http://www.albionresearch.com/misc/urlencode.php for doing quick encoding/decoding of a string.
Programmatically, you can do this:
use URI::Escape;
my $str = uri_unescape("%20%D1%EB");
print $str . "\n";
or simply:
perl -MURI::Escape -wle'print uri_unescape("%20%D1%EB");'