A friend of mine in Romania (Andrei D.) wanted some help with automating data collection from sucuri yet was having some issues getting past the login portion. He provided me with the following Perl solution he was hacking at.
Andrei's Perl
#!/usr/bin/perl -w
use WWW::Mechanize;
use Storable;
use utf8;
use Text::Unidecode;
use HTTP::Cookies;
my $url = 'https://dashboard.sucuri.net/login/';
my $mech_ua = 'Client API';
my $login = '';
my $pass = '';
my $token;
my $mech = WWW::Mechanize->new(
autocheck => 0,
agent => $mech_ua,
cookie_jar => HTTP::Cookies->new( file => "/root/.cookies.txt", autosave => 1 )
);
$mech->get($url);
foreach ( $mech->content() ) {
$token = $& if $_ =~ /[\w]{32}/m; # grab token for form submission (i think it needs to be used for the SUCURI cookie also)
}
print "Logging in with: $login :: $pass :: $token\n";
$mech->submit_form(
form_number => 1,
fields => {
email1 => $login,
passw1 => $pass,
sucuritoken => $token,
doLogin => 'Login'
},
);
if ( $mech->success ) {
my $status = $mech->status();
print "Submitted and got: $status\n";
print "Fullreturn: ".$mech->content();
my $u2 =
'https://waf.sucuri.net/?settings&site=domain.com&panel=api';
$mech->get($u2);
my $parse;
print "Fullreturn: " . $mech->content();
my @lines = split( "\n", $mech->content() );
foreach (@lines) {
$_ =~ s/([^[:ascii:]]+)/unidecode($1)/ge;
$parse = $&
if $_ =~ /monospace.*GRAB_LINE_WITH_API_KEY\/.*\new(
cookie_jar => HTTP::Cookies->new(),
requests_redirectable => [],
timeout => 10,
agent => $user_agent,
);
my $req = GET $url;
my $token;
if ( $ua->request($req)->as_string =~ m/name="sucuritoken"\svalue="(\S+)"/ ) {
$token = $1;
} else {
print "No token found\n";
exit;
}
$req = POST $url,
[
email1 => $username,
passw1 => $password,
sucuritoken => $token,
doLogin => "Login",
];
$ua->request($req);
$req = GET $other_url;
print $ua->request($req)->as_string;
Moral of the story, WWW::Mechanize was great for scraping websites in the 90’s and 00’s. Update to Python or use lower level libs when dealing with mechanize session issues.
Note: I did not try but for 20 minutes while also juggling a conference call to debug his code. It may very well be functional and may only need minor tweaks – I just took the easy route because I haven’t touched Perl in a few months time.
Additional content from archive:
A friend of mine in Romania (Andrei D.) wanted some help with automating data collection from sucuri yet was having some issues getting past the login portion. He provided me with the following Perl solution he was hacking at:
Andrei’s Perl Attempt
#!/usr/bin/perl -w
use WWW::Mechanize;
use Storable;
use utf8;
use Text::Unidecode;
use HTTP::Cookies;
my $url = 'https://dashboard.sucuri.net/login/';
my $mech_ua = 'Client API';
my $login = '';
my $pass = '';
my $token;
my $mech = WWW::Mechanize->new(
autocheck => 0,
agent => $mech_ua,
cookie_jar => HTTP::Cookies->new( file => "/root/.cookies.txt", autosave => 1 )
);
$mech->get($url);
foreach ( $mech->content() ) {
$token = $& if $_ =~ /[\w]{32}/m; # grab token for form submission (i think it needs to be used for the SUCURI cookie also)
}
print "Logging in with: $login :: $pass :: $token\n";
$mech->submit_form(
form_number => 1,
fields => {
email1 => $login,
passw1 => $pass,
sucuritoken => $token,
doLogin => 'Login'
},
);
if ( $mech->success ) {
my $status = $mech->status();
print "Submitted and got: $status\n";
print "Fullreturn: ".$mech->content();
my $u2 =
'https://waf.sucuri.net/?settings&site=domain.com&panel=api';
$mech->get($u2);
my $parse;
print "Fullreturn: " . $mech->content();
my @lines = split( "\n", $mech->content() );
foreach (@lines) {
$_ =~ s/([^[:ascii:]]+)/unidecode($1)/ge;
$parse = $&
if $_ =~ /monospace.*GRAB_LINE_WITH_API_KEY\/.*\</m;
print $_;
}
}
else {
print "Error reaching login page!\n";
exit 1;
}
His code was pulling the token and logging in but when pulling the “waf” url it was redirecting back to the login page so there was an issue somewhere. I was in the middle of a conference call at the time so instead of debugging his code outright I decided to just write my own solutions for him to work off of.
I did this first by porting his code to python.
My Python Login
#!/usr/bin/env python
"""
Login to Sucuri Dashboard
And Pull API Key
"""
import requests
from lxml import html
# Setup
url = 'https://dashboard.sucuri.net/login/'
user_agent = 'User-Agent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5'
username = ''
password = ''
# Get login page
session = requests.session()
result = session.get(url)
tree = html.fromstring(result.text)
# Get token
token = list(set(tree.xpath('//*[@id="loginform"]/input[3][email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */')))[0]
if token:
# Build Payload
payload = {
"email1": username,
"passw1": password,
"sucuritoken": token,
"doLogin": "Login",
}
# Login
result = session.post(
url,
data = payload,
headers = dict(referer=url)
)
# Get API Dash
url = 'https://waf.sucuri.net/?settings&site=domain.com&panel=api'
result = session.get(
url,
headers = dict(referer = url)
)
print result.text
else:
print "Sorry, no token found; please try again"
After successfully porting to Python I then ported my code back to Perl for Andrei to work with.
My Perl Login
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Cookies;
use LWP::UserAgent;
use HTTP::Request::Common qw/POST GET/;
# Setup
my $url = 'https://dashboard.sucuri.net/login/';
my $other_url = 'https://waf.sucuri.net/?settings&site=domain.com&panel=api';
my $user_agent = 'User-Agent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5';
my $username = '';
my $password = '';
# Get token
my $ua = LWP::UserAgent->new(
cookie_jar => HTTP::Cookies->new(),
requests_redirectable => [],
timeout => 10,
agent => $user_agent,
);
my $req = GET $url;
my $token;
if ( $ua->request($req)->as_string =~ m/name="sucuritoken"\svalue="(\S+)"/ ) {
$token = $1;
} else {
print "No token found\n";
exit;
}
$req = POST $url,
[
email1 => $username,
passw1 => $password,
sucuritoken => $token,
doLogin => "Login",
];
$ua->request($req);
$req = GET $other_url;
print $ua->request($req)->as_string;
Moral of the story, WWW::Mechanize was great for scraping websites in the 90’s and 00’s. Update to Python or use lower level libs when dealing with mechanize session issues.
Note: I did not try but for 20 minutes while also juggling a conference call to debug his code. It may very well be functional and may only need minor tweaks – I just took the easy route because I haven’t touched Perl in a few months time.
Tell your friends...