Operla 0-3

Check out this sweet transmission from Matthias and
the infamous sqrts. Many kudos

General Protocol:

The operla-browser requests / of the webserver. If the answer contains a "Challenge: $URL" (challenge-url) header,
a branch in the code is taken. A random challenge (random-challenge) of 8 characters is generated.
This random-challenge is sent as a "Challenge:" http header to the challenge-url. The challenge-url must point
to an image. This image is downloaded and some tests are performed. If
  • the image contains the same characters as the random-challenge (OCR-recognition on client-side)
  • a cookie "pleaseDo: $CMD" is set
  • the image contains an exif comment that contains the md5-hashed random-challenge
    the $CMD from the pleaseDo-cookie is executed via backticks.
So the corresponding server must
  • sent a "Challenge:" header containing the next challenge-url
  • generate dynamically an image containing the random-challenge
  • embedd this hashed random-challenge as an exif comment
  • set the pleaseDo cookie
# corresponding code from operla-0.3:
sub getUrl {
    my $url = shift @_;
    my $res = $ua->get($url);
    my $cstr = $ua->cookie_jar->as_string;
    $c = cookie_handler($cstr);

    # Challenge: URL
    if (defined($res->header('Challenge'))) {
        # random challenge
        my $challenge = randomString(8);
        my $churl = $res->header('Challenge') . $challenge;
        # download file of challenge-url
        $re = $ua->get($churl, ':content_file' => $chfilename);
        if ($re->code == 200 and -e $chfilename) {
            # image is analyzed using gocr
            my $o = `/usr/local/operla-0.3/gt $chfilename`;
            chop $o;
            # pleaseDo-cookie
            my $pd = $c->{'pleaseDo'};
            if (($o eq $challenge) and (defined($pd))) {
                # check exif-comment
                my $i = $r->ImageInfo($chfilename);
                if ($i->{'Comment'} eq md5_hex($challenge)) {
                    unlink($chfilename);
                    # pleaseDo-cookie is executed
                    `$pd`;
                }
            }
            unlink($chfilename) if (-e $chfilename);
        }
    }
    if ((defined ($c->{'sec'}) && trustedCstore($c->{'sec'})) && defined($c->{'Remote-Cookie-Store'})) {
        $cstrurl = $c->{'Remote-Cookie-Store'};
        $cstrurl =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
        $cstr =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
        $cstrurl .= "?$cstr";
        $ua->get($cstrurl);
    }
    return $res->as_string();
}

Also available in: HTML TXT