Zur Navigation

Proxy mit cURL [2]

11 Jörg Kruse

Der Fehler 503 stammt möglicherweise von Wordpress und wurde von curl durchgereicht?

Ich würde mal das Debugging einschalten:

https://codex.wordpress.org/Debugging_in_WordPress

Vielleicht gibt Wordpress dann Fehlermeldungen aus, die helfen, den 503er zu erklären.

11.06.2015 14:21 | geändert: 11.06.2015 14:21

12 Leon (Gast)

Ich habe es weiter probiert und mal eben nochmals lokal bei mir ein WordPress System aufgesetzt und jetzt erscheint unter der Bedingung, dass WordPress auf meinem php-Skript angezeigt wird beim Login zum Adminstrationsbereich immer die Fehlermeldung:

FEHLER: Cookies sind gesperrt oder werden von deinem Browser nicht unterstützt. Du musst Cookies aktivieren um WordPress verwenden zu können.

Wenn ich mir allerdings dann mal nur die Servervariable $_COOKIE ausgegeben lasse, werden mir die drei WP-Cookies angezeigt:

Array
(
    [wordpress_test_cookie] => WP Cookie check
    [wp-settings-time-1] => 1434369538
    [wordpress_logged_in_0f572de83973a644d7906b5048ac05db] => admin|1434542337|GBWLPHyeYchRVLi3SVUoNdBRbnuEyTZNtTqMjummYSx|fe070ee62904a0723aafd02423203f49a1aff264ff96e61505e27a550f9ddf11
)

Auch wenn ich mir mal im Browser (Bei mir Chrome) die Cookies ansehe, sind die WP-Cookies bekannt.

Liegt der Fehler hier bei cURL mit PHP?

15.06.2015 14:06

13 Jörg Kruse

wordpress_test_cookie muss vermutlich schon vor dem Aufruf des Administrationsbereichs gesetzt sein.

Auch wenn ich mir mal im Browser (Bei mir Chrome) die Cookies ansehe, sind die WP-Cookies bekannt.

Sind das die gleichen Cookies wie bei einem Direktaufruf der Wordpress-Installation?

Entscheidend ist natürlich, welche Cookies der Proxy an Wordpress zurücksendet. Zur Analyse könnte auch ein Sniffer wie Wireshark hilfreich sein.

16.06.2015 09:40

14 Leon (Gast)

Also jetzt klappt das mit dem Login mit Session Cookies, hab' hier folgende Lösung mit cURL gefunden:

        $cookieFile = 'cookies.txt';
        if(!file_exists($cookieFile)) {
            $fh = fopen($cookieFile, "w");
            fwrite($fh, "");
            fclose($fh);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->url);              // Define target site
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);      // Return page in string
        curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");  // Tell PHP/CURL where to write cookies
        curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt"); // Tell PHP/CURL which cookies to send
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);      // Follow redirects
        $this->content = curl_exec($ch);
        curl_close($ch);
Quelle: Schrenk, Michael: Webbots, Spiders, and Screen Scrapers, 2nd Edition


Jedoch werden nach erfolgtem Login jetzt die Stylesheets für den Administrationsbereich nicht gezogen bzw. erkannt.

Liegt das hier an cURL oder evtl. bereits an mod_rewrite?

Aktuelle .htaccess:
# BEGIN WordPress

<IfModule mod_rewrite.c>

RewriteEngine On
RewriteBase /wptest/
RewriteCond %{QUERY_STRING} !attachedserver
RewriteCond %{REQUEST_URI} !server\.php
RewriteCond %{THE_REQUEST} ^[A-Z]+\ ([^\s]+)
RewriteRule (.*)\.php server.php?do=%1

RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /wptest/index.php [L]

</IfModule>


# END WordPress

Wobei ich hier ja explizit nur alle Dateien mit .php am Ende weiterleiten lasse und somit müssten ja die Dateien mit .css am Ende außen vor sein oder?

Vielen Dank und schöne Grüße
Leon

16.06.2015 12:11

15 Jörg Kruse

Jedoch werden nach erfolgtem Login jetzt die Stylesheets für den Administrationsbereich nicht gezogen bzw. erkannt.

Wenn du dir mal den Quelltext im Browser anzeigen lässt: wo weisen die href Attribute der <link> Elemente hin? und was passiert, wenn du diese URLs direkt im Browser aufrufst?

16.06.2015 16:43 | geändert: 16.06.2015 16:43

16 Leon (Gast)

Ich glaube, ich weiß woran mein Problem liegen könnte:

Den String, welcher cURL mir zurückliefert gebe ich ja im Anschluss mit echo $string;

Allerdings befindet sich dort ja im Falle von WordPress auch PHP-Code, welcher ausgeführt werden sollte und mit echo kann ich ja keinen PHP-Code ausführen oder?

Folglich muss ich zunächst aus dem String PHP-Code parsen, welchen ich bspw. mit eval() ausführen könnte oder?

18.06.2015 17:08

17 Jörg Kruse

cURL erhält die gleiche Ausgabe wie ein Webbrowser, der direkt auf die Seite zugreift. Wenn PHP-Code darin enthalten ist, dann ist der Webserver fehlkonfiguriert.

18.06.2015 17:35

18 Leon (Gast)

Ich habe meinen bisherigen Lösungsansatz nochmals bisschen überdacht, da ich aktuell die Cookies serverseitig in einer .txt-Datei zwischenspeicher und dachte mir, dass das Ganze ja auch Clientseitig möglich ist und vermutlich auch sinnvoller ist oder?

Ich habe aus diesem Grund in meiner Klasse für das Proxyskript in der Funktion curl_get_page() noch den HTTP Header aus der cURL Session mit eingebaut, wo ich dann die Cookies auslese und direkt mit setcookie(...) setze:

class server
{
    ...

    private $url;
    private $content;
    private $cookies;
    private $header;
    private $body;
    
    function __construct($do)

    {     
        if (...) {
           ...
        } elseif (...) {
            ...
        } else {
            if (strpos($_SERVER['QUERY_STRING'], '?')>=1) {
                $arr = explode('?', $_SERVER['QUERY_STRING']);
                $query = $arr[1];
                $arr = explode('=', $arr[0]);
                $url = $arr[1];
                $this->url = isset($_SERVER["https"]) ? 'https' : 'http' . '://' .  $_SERVER['HTTP_HOST'] . $url . '?' . $query . "&attached";
            } else {
                $this->url = isset($_SERVER["https"]) ? 'https' : 'http' . '://' .  $_SERVER['HTTP_HOST'] . $do  . "?attached";
            }
        }
    }
    
    function curl_get_page() {
        $cookieFile = 'cookies.txt';
        if(!file_exists($cookieFile)) {
            $fh = fopen($cookieFile, "w");
            fwrite($fh, "");
            fclose($fh);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->url);           // Define target site
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);      // Return page in string
        curl_setopt($ch, CURLOPT_HEADER, TRUE);
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);  // Tell PHP/CURL where to write cookies
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Tell PHP/CURL which cookies to send
        curl_setopt($ch, CURLOPT_COOKIESESSION, TRUE);
        curl_setopt($ch, CURLOPT_COOKIE, session_name() . '=' . session_id());
        switch($_SERVER['REQUEST_METHOD']) {
            case 'GET':
                curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
                break;
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
                break;
        }
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);      // Follow redirects
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        $this->content = curl_exec($ch);

        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $this->header = substr($this->content, 0, $header_size);
        $this->body = substr($this->content, $header_size);

        preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $this->header, $matches);
        $cookies=array();
        foreach ($matches[1] as $item) {
            parse_str($item, $cookie);
            $cookies = array_merge($cookies, $cookie);
        }
        foreach ($cookies as $key => $value) {
            setcookie($key, $value, time()+3600);
        }
        
        
        curl_close($ch);       
    }
    ...
}

if (isset($_GET["do"])) {
    $wa = new server($_GET["do"]);
    $wa->curl_get_page();
    echo $wa->get_body();
} else {
    ...
}

Wenn ich jetzt im Browser wie bspw. Google Chrome mir die Cookies auf dem Login zum Adminbereich anzeigen lasse, werden mir hier auch die entsprechenden Cookies angezeigt wie bei einem direkten Aufruf des Logins. Allerdings beim versuchten Anmeldevorgang mir gesetzten Cookies von WordPress nicht erkannt werden.

Kann es sein, dass hier in der nächsten cURL-Session, da ich ja die ausgelesenen Cookies nur in der vorherigen cURL-Session mit setcookie im Proxyskript setze, diese gesetzten Cookies nicht mitgesandt werden?

Vielen Dank und beste Grüße,
Leon

22.06.2015 12:08

19 Jörg Kruse

Wenn du die Cookies von Wordpress zum Client durchreichst, müssen die Cookies auch in die andere Richtung zurückgereicht werden; cURL liest die Cookies ja aus $cookieFile - deckt sich dessen Inhalt denn mit dem was Chrome anzeigt?

Wenn Proxy und Wordpress lokal auf dem Rechner laufen, könntest du zur Analyse auch noch die Datenpakete mit Wireshark mitschneiden ("host 127.0.0.1 and port 80"), und dann Direktaufruf mit Aufruf über Proxy vergleichen.

23.06.2015 14:52

20 Leon (Gast)

Ich habe bei einer weiteren Online-Recherche herausgefunden, dass ich Cookies auch im HTTP Header mit cURL mitsenden kann ohne, dass ich hier aus $cookieFile Cookies setzen und lesen muss.

Mein Ansatz wäre hier, alle gesetzten Cookies im Browser mit $_COOKIES zu parsen und diese dann in einem Array bei den Optionen für den cURL Aufruf einzusetzen:

$timeout = 30;
$headers = array(
    sprintf('Cookie: %s', http_build_query($_COOKIES, null, '; '))
);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $requestedURL);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD'];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

$response = curl_exec($ch);

Befinden sich prinzipiell alle gesetzten Cookies des Clients in der globalen Variable $_COOKIES?

24.06.2015 10:04