Thema: Cookies in Perl
-
21. 12. 2011, 19:02 #1
Cookies in Perl
Liebes Gulliboard,
ich habe ein Problem. Ich möchte gerne mithilfe eines Perlskriptes auf eine Webseite zugreifen, die Cookies verlangt. Dazu logge ich mich zuerst ein, indem ich die Variablen, nachdem ich sie übermittelt habe, per POST an die Hauptseite übergebe; ich erhalte ein Cookie. Dieses Cookie möchte ich gerne an eine Unterseite mitsenden um sie lesen zu können. Leider klappt das nicht so ganz, hier der Code:
Könnt ihr mir helfen? Vielen Dank.Code:#!/usr/bin/perl -w use strict; use LWP::UserAgent; use HTTP::Cookies; my $browser=LWP::UserAgent->new; my $cookie_jar=HTTP::Cookies->new(file=>"cookies_lwp.dat", autosave=>1); my $url="http://www.wechall.net"; my $url_2="http://www.wechall.net/challenge/training/programming1/index.php?action=request"; my $obfuscation; my $response; my $result; #Die Webseite hat eine zufällige Kennung, die bei jedem Start anders ist und mithilfe von Regulären #Ausdrücken in $obfuscation gespeichert wird. $cookie_jar beinhaltet die Cookies und liest/speichert #sie aus/in cookies_lwp.dat, die automatisch erstellt wird. $browser ist der "Browser" mit dem ich #die URL abfrage. $response->content beinhaltet den Quelltext jeder Webseite die ich aufrufe, in $result #speichere ich das Ergebnis nocheinmal, damit ich nicht immer den Pfeiloperator verwenden muss. $browser->cookie_jar($cookie_jar); #Zunächst muss ich besagte zufällige Zeichenfolge finden; dazu rufe ich die Loginseite auf und speichere #erst einmal den gesamten Quelltext ab. $response=$browser->get($url); $result=$response->content; #Die Folgende Schleife sucht den Zufallswert, der nunmal "gwfcsrf" heisst und speichert ihn in $obfuscation. while ($result=~m/name="gwfcsrf" value="(.+?)"/gs) { $obfuscation=$1; } #Nun sind alle Eingaben die zum Einloggen (und zur Erschließung der Cookieinformationen) nötig sind #vorhanden. Die Einträge in [eckigen] Klammern habe ich ersetzt, da ich meine Accountinformationen ungern #weitergebe. $response=$browser->post($url,"username",[username]","password","[passwort]","bind_ip","on","login","Login","gwfcsrf",$obfuscation); $response=$browser->get($url_2); $result=$response->content; print $result;
-
21. 12. 2011, 20:17 #2
Re: Cookies in Perl
Das Problem ist nicht in deiner (durchaus korrekten) Verwendung des HTTP::Cookies-Objekts als Cookie-Jar zu suchen, sondern in deinem inkorrekten Aufruf der post()-Methode des LWP::UserAgent-Objekts, welche zu einem fehlerhaften POST-Request führt. Dein Aufruf führt dazu, dass die als POST-Daten vorgesehen Zusatzdaten in Form von HTTP-Request-Headern übergeben werden (vgl. http://search.cpan.org/~gaas/libwww-...P/UserAgent.pm, in Speziellen die post()-Aufrufsyntax); das Problem lässt sich mittels eines Netzwerksniffers wie z.B. Wireshark und einem passenden Filter (etwa http.request in Wireshark) leicht beobachten.
Passender wäre die Übergabe eines Hashs, welcher die als POST-Daten zu übermittelnden Formularfelder und deren Inhalte enthält, etwa
Abgesehen davon ist dein POST-URI nicht korrekt. Die im Formular eingegebenen Daten werden nicht an http://www.wechall.net/, sondern an http://www.wechall.net/login übermittelt (wie du dem action-Attribut des form-Elements entnehmen kannst).Code:$response = $browser->post("...", { "username"=>"...", "password"=>"...", ... } );
-
21. 12. 2011, 20:46 #3
Re: Cookies in Perl
Lieber Kugelfisch,
vielen Dank für deine Antwort. Ich hätte doch noch ein paar Fragen um genau zu verstehen was ich falsch mache.
Was genau ist der Unterschied zwischen der Übergabe der Informationen in Variablen und der Übergabe in Form eines Hashes? Werden letztendlich nicht "nur" Zeichen übergeben?Passender wäre die Übergabe eines Hashs, welcher die als POST-Daten zu übermittelnden Formularfelder und deren Inhalte enthält
Der Zielserver sucht also im body nach der Datei aber tatsächlich befinden sich die Informationen im HTTP-Header? Das würde erklären warum die Cookies zwar mitgesandt werden, aber nicht erkannt werden. Die stattfindende Anmeldung (die tatsächlich stattfindet; ich finde meinen Benutzernamen in $result wieder) lässt sich damit aber nicht erklären. Zumindest nicht für meine Begriffe.dass die als POST-Daten vorgesehen Zusatzdaten in Form von HTTP-Request-Headern übergeben werden
Ich werde morgen die Ratschläge umsetzen, vielen Dank schoneinmal für deine Mühen.
-
21. 12. 2011, 22:00 #4
Re: Cookies in Perl
Nein, durch die Übergabe eines Hashes (genauer: einer Hash-Referenz) wird die überladene Methode*
aufgerufen, die Parameter sind ein Skalar und eine Hash-Referenz. Die Folge ist, dass die im übergebenen Hash abgelegten Einträge als Formulardaten interpretiert und nach passender Codierung im POST-Body übertragen werden. Dein Aufruf führt die überladene Methode*Code:$ua->post( $url, \%form )
aus, wobei das Content-Feld leer bleibt. Gemäss der verlinkten Dokumentation bezeichnen die übrigen Parameter zu setzende HTTP-Request-Header.Code:$ua->post( $url, $field_name => $value,... Content => $content )
Zu (*): Der Begriff überladene Methode bezieht sich auf das Äquivalent in anderen, strikter typisierten Programmiersprachen. In Perl wird eine Methode oder Funktion nicht im engeren Sinne überladen, da gar keine fixe Parameterliste existieren muss. Die Funktion wertet bloss die Typen der übergebenen Parameter aus und reagiert darauf entsprechend. Das Ergebnis ist freilich dasselbe.
In mitgeschnittenen Requests fallen die Unterschiede sofort auf. Die von mir vorgeschlagene Aufrufsyntax liefert einen Request der Form
während dein Aufruf einen Request der FormPOST /login HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: www.wechall.net
User-Agent: libwww-perl/5.836
Content-Length: 90
Content-Type: application/x-www-form-urlencoded
Cookie: WC4_SID=...
Cookie2: $Version="1"
bind_ip=on&password=...&gwfcsrf=...&login=Login&username=...
erzeugt. Zu bemerken ist, dass das Cookie in beiden Fällen korrekt übermittelt wird, die Zugangsdaten jedoch bei deinem Aufruf nicht im POST-Body, sondern im HTTP-Header übermittelt werden, während der POST-Body leer bleibt.POST / HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: www.wechall.net
User-Agent: libwww-perl/5.836
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
Bind-Ip: on
Gwfcsrf: ...
Cookie: WC4_SID=...
Cookie2: $Version="1"
Login: Login
Password: ...
Username: ...
Das wäre angesichts der inkorrekten Übermittlung der Login-Daten in der Tat seltsam. An welcher Stelle findet sich dein Benutzername im Antwort-Body welches Requests? Hast du möglicherweise unbewusst noch eine (gültige?) Session eines früheren, erfolgreichen Login-Versuchs genutzt? Lösche im Zweifelsfall deine Cookie-Jar-Datei (cookies_lwp.dat).Geändert von Kugelfisch23 (21. 12. 2011 um 22:06 Uhr) Grund: Bemerkung zu überladenen Funktionen/Methoden in Perl.
-
22. 12. 2011, 08:45 #5
Re: Cookies in Perl
Für solche automatisierte Webseitensteuerungen empfehle ich immer wieder gerne WWW::Mechanize, damit lässts sich sehr gemütlich arbeiten.
mfG
-
23. 12. 2011, 18:21 #6
Re: Cookies in Perl
So, ich habe den Code nun für ein Objekt von WWW::Mechanize umgeschrieben. Komfortabler ist es auf jeden Fall, ich habe jedoch leider immer noch bescheidenen Erfolg. Ich würde gerne von euch wissen:
1. Wie kann ich die Checkbox bei "Restrict session to IP" anwählen? $agent->tick() funktioniert nicht, weil kein Wert für die Checkbox (der meines Erachtens nur 0 oder 1 sein kann) gefunden wird.
2. Wie kann ich die Cookies bzw die Korrektheit der Cookieinformationen überprüfen?
3. Welche Eselei meinerseits hält mich auch diesesmal vom weiterkommen ab?
Hier mein Code soweit:
Vielen Dank für eure Hilfe soweit.Code:#!/usr/bin/perl -w use strict; use LWP::UserAgent; use HTTP::Cookies; use WWW::Mechanize; my $agent=WWW::Mechanize->new; my $url="http://www.wechall.net"; my $url_2="http://www.wechall.net/challenge/training/programming1/index.php?action=request"; my $content; my $obfuscation; $agent->cookie_jar(HTTP::Cookies->new); $agent->get($url); $content=$agent->content(format=>'text'); while($content=~m/name="gwfcsrf" value="(.+?)"/gs) { $obfuscation=$1; } $agent->form_id('wc_toplogin'); $agent->set_fields(username=>'xxx',password=>'xxx',bind_ip=>"checked",gwfcsrf=>$obfuscation,login=>"Login"); $agent->submit(); $agent->get($url_2); print $agent->content;
-
23. 12. 2011, 23:24 #7
Re: Cookies in Perl
Der Wert des value-Attributs kann im Allgemeinen nicht nur 1 oder 0 sein, da mehrere Checkboxen desselben Namens existieren können, welche (anders als Radio-Buttons) auch gleichzeitig angewählt sein können. Um diese unterscheiden zu können, können verschiedene value-Attribute genutzt werden. In diesem Fall fehlt das value-Attribut, WWW::Mechanize nimmt (wie viele verbreitete Browser auch) in diesem Fall offenbar on als Standardwert an. Daher wäre
passend.Code:$agent->tick('bind_ip','on');
Du könntest die Cookies natürlich aus dem Cookie-Jar auslesen, doch würde der Inhalt der Cookies (in diesem Fall bloss eine Session-ID) nicht zwingend Rückschlüsse darauf zulassen, ob dadurch ein bestimmter registrierter Benutzer authentifiziert wird. In sofern musst du entweder das zurückgelieferte HTML-Dokument nach dem Anmeldeversuch auswerten oder blind versuchen, eine beliebige, ausschliesslich registrierten Benutzern zugängliche Seite zu laden - misslingt dies, bist du offensichtlich nicht korrekt authentifiziert.
Du missverstehst offenbar das Konzept von WWW::Mechanize. Die set_fields()-Methode ist nicht dazu gedacht, beliebige POST-Daten zu setzen, sondern lediglich dazu, bestimmte Formularfelder im geladenen HTML-Dokument mit Werten zu füllen - genau wie du dies im Browser tun würdest. Du musst versteckte Formularfelder (input-Elemente des Typs hidden) ebenso wenig `ausfüllen` wie z.B. den Login-Button, allerdings musst du angeben, dass der Login-Button zum Abschicken des Formulars genutzt werden soll.
Dieses automatische HTML-Parsing ist, was WWW::Mechanize auszeichnet (und der Grund, weshalb auch ich WWW::Mechanize empfohlen hätte, wenn das Formular nicht trivial wäre). Zum Beispiel:
Code:my $agent=WWW::Mechanize->new; $agent->get('http://www.wechall.net/'); $agent->form_id('wc_toplogin'); $agent->set_fields(username=>'foobar', password=>'123456'); $agent->tick('bind_ip','on'); $agent->click('login'); # ... weitere URIs anfordern ...Geändert von Kugelfisch23 (23. 12. 2011 um 23:31 Uhr)
-
24. 12. 2011, 14:14 #8
Re: Cookies in Perl
Vielen herzlichen Dank für eure Hilfe. Hier der Code mit dem es letztendlich geklappt hat:
Leicht verändert, damit die Lösung der Challenge nicht dargelegt wird.Code:#!/usr/bin/perl -w use strict; use WWW::Mechanize; use HTTP::Cookies; my $agent=WWW::Mechanize->new; my $url="http://www.wechall.net"; $agent->cookie_jar(HTTP::Cookies->new); $agent->agent_alias("Linux Mozilla"); $agent->get($url); $agent->form_id('wc_toplogin'); $agent->set_fields(username=>'foo',password=>'bar'); $agent->tick('bind_ip','on'); $agent->click('login');
Edit: Doppelposts sind verboten und werden mit Steinigungen bestraft, deswegen packe ich das in den selben Post.
Es gibt noch eine (ähnlich gestaltete) Seite welche ich mithilfe von WWW::Mechanize abfragen möchte, nämlich www.hackquest.com. Ich habe (analog zu oben) ein Skript geschrieben welches die nötigen Informationen in die Felder einträgt. Das scheint auch zu klappen, nur kann ich die Seite die ich aufrufen möchte nicht vernünftig aufrufen, ich herhalte die Meldungen, das Cookie sei kaputt.
Hier mein Code:
Was mache ich hier falsch? Ich kann eine Seite aufrufen die ich nur mit gesetztem Cookie betrachten kann, zum Beispiel das Benutzerzentrum. Dort werde ich sogar mit Nicknamen begrüßt, der Server kennt mich auf jeden Fall.Code:use strict; use WWW::Mechanize; use HTTP::Cookies; use String::CRC32; my $agent=WWW::Mechanize->new; my $url_1="http://hackquest.com/"; my $url_2="http://hackquest.com/modules/HackQuest/hacking/1239845666/service.php"; $agent->cookie_jar(HTTP::Cookies->new); $agent->get($url_1); $agent->form_number(1); $agent->set_fields(uname=>'foo'pass=>'bar'); $agent->tick('rememberme','1'); $agent->click(); $agent->get($url_2);Geändert von wolfsjunge (24. 12. 2011 um 17:36 Uhr)
-
27. 12. 2011, 14:22 #9
Re: Cookies in Perl
Mutmasslich wird (wohl anhand einer serverseitig gespeicherten Session oder anhand eines erst dann gesetzten Cookies - oder zumindest anhand des Referer-Headers) überprüft, ob du die Seite, welche den Link zu http://hackquest.com/modules/HackQue...66/service.php enthält, tatsächlich besucht hast bzw. diesem Link gefolgt bist. Besuche mittels WWW::Mechanize die Seite, welche den Link enthält, und folge dann dem Link (was mittels der followLink()-Methode von WWW::Mechanize sehr komfortabel möglich ist).
-


Zitieren

mehr lesen...







Resident Evil 6 erscheint in...
Heute, 15:21 in gulli:news