[PHP] URL laden met cURL veilig?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Ik ben bezig aan een klein projectje, waarbij gebruikers een URL kunnen invullen in een form veld. Deze wordt met een AJAX POST request naar de server gestuurd. Daar wordt de URL geïnspecteerd en geladen met cURL, zoals hieronder getoond.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
    //Load generic user input filter
    require_once("class.inputfilter_clean.php");
    $filter = new InputFilter();
    
    //Clean input URL, and check if it's an http address
    function filter_url($url) {
        global $filter;
        $url = $filter->process($url);
        $url_parsed = parse_url($url);
        if(isset($url_parsed)) {
            $scheme = $url_parsed['scheme'];
            if(isset($scheme) && $scheme=="http") {
                return $url;
            }
        }
        die("Must use http protocol");
    }

    //Load URL with cURL, following redirects if necessary
    function curl_redirect_exec($ch, &$redirects, $curlopt_header = false) {
        //Include headers in response, and load response as a string variable
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        //Load the webpage
        $data = curl_exec($ch);
        
        //Die if result is anything other than text/html
        $info = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        if(substr($info,0,9) != "text/html")
            die("Could not read URL");

        //Handle specific http return codes
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if(isset($http_code) {
        
            //handle redirects
            if ($http_code == 301 || $http_code == 302) {
                //find redirect url
                list($header) = explode("\r\n\r\n", $data, 2);
                $matches = array();
                preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
                $url = filter_url(trim(array_pop($matches)));
    
                //execute this function on redirect url
                curl_setopt($ch, CURLOPT_URL, $url);
                $redirects++;
                return curl_redirect_exec($ch, $redirects);
            }
    
            //handle html
            if ($http_code == 200)
            {
                if ($curlopt_header)
                    return $data;
                else {
                    list(,$body) = explode("\r\n\r\n", $data, 2);
                    return $body;
                }
            }
        }

        //Failure (received 404 or no http code at all)
        die("Invalid URL");
    }
    
    //Clean URL
    $url = filter_url($_POST['url']);

    //Start cURL, with cleaned URL
    $ch = curl_init($url);

    //Load URL, redirect if needed, and get resulting HTML
    $html = curl_redirect_exec($ch);

    //Stop cURL
    curl_close($ch);

    //Parse HTML, store in database, etc
    //...
?>


Nou vraag ik me af of ik de zaak zo voldoende heb dichtgetimmerd. Ik haal de url eerst door een filter (die controleert op sql injectie etc) en accepteer alleen URL's die:
  • Kunnen worden geparsed door PHP
  • Beginnen met 'http://'
  • (na laden) verwijzen naar een text/html document
  • (na laden) http code 301, 302 of 200 geven
Natuurlijk moet ik de resulterende $html nog met argwaan behandelen. Zien jullie verder mogelijkheden om stoute dingen te doen, door bepaalde URL's in te voeren of door een aanvalssite te bouwen?

Verder hoor ik graag andere ervaringen over het gebruik van cURL met door de gebruiker ingegeven URL's :)

TabCinema : NiftySplit


Acties:
  • 0 Henk 'm!

Verwijderd

Ik heb geen zin om je hele code te bekijken, maar het lijkt mij verstandig om ook het volgende te controleren:
- Geen username/password in url zoals http://username:password@hostname/
- Geen poort in de url zoals http://hostname:1234/
- Haal de url door bijvoorbeeld http://code.google.com/intl/de/apis/safebrowsing/ (deze database is ook te downloaden, die zou je dan even op moeten zoeken)
- Zet een timeout op curl op bijvoorbeeld 2s, zodat je eigen server niet teveel belast wordt

Ik snap niet echt wat je wil, wil je een webproxy maken?

Zo ja:
- Verwijder flash, activex, moonlight/silverlight en andere objecten
- Verwijder javascript
- Herschrijf url's zodat die ook langs je proxy gaan
- Zie verder de bestaande webproxies

Acties:
  • 0 Henk 'm!

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Ik probeer geen webproxy te maken. Mijn webapp brengt gebruikers op de hoogte van veranderingen in een andere webpagina; iets waarvoor je momenteel een browserplugin nodig hebt.

Over je tips:
- http://username:password@... is toch niet gevaarlijk voor mij, als server?
- waarom zijn poorten gevaarlijk? Of ik nou verbinding maak met 80 of 1234 lijkt mij niet zo veel verschil maken?

Die database en een timeout zijn goede ideeën!

TabCinema : NiftySplit


Acties:
  • 0 Henk 'm!

Verwijderd

Hier zijn vaak betere oplossingen voor, zoals RSS en Atom. Tegenwoordig heeft google ook een nieuw protocol het leven ingeroepen: PubSubHubBub. Hiermee kan je -bijna- realtime updates ontvangen van websites. De websites moeten dit dan wel ondersteunen. Dit scheelt jou en het web ontzettend veel (netwerk)belasting. Denk er maar eens over na of dit jouw dienst overbodig maakt ;). Ik heb een vermoeden dat deze dienst gebruikt gaat worden voor onder andere iBood 'watchen'?

Poorten en usernames etc kan je er inderdaad wel toestaan bij zo'n dienst. Zorg er trouwens voor dat je het een en ander limiteert (x aantal requests per ipadres per tijdseenheid en een totaal aantal requests per tijdseenheid) en zo nodig een captcha in laat vullen. Controleer ook of curl bij die timeout het downloaden van het html bestand meeneemt!

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Hangt er heel erg vanaf waarvoor je dit wilt gebruiken. Maar in principe zou ik altijd met een whitelist werken.

Nu kan iemand via wat creatieve url's aanroepen jouw server een hackpoging laten doen op andermans server. Dan ben jij in 1e instantie aansprakelijk

Acties:
  • 0 Henk 'm!

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Gomez12 schreef op zaterdag 13 maart 2010 @ 16:02:
Hangt er heel erg vanaf waarvoor je dit wilt gebruiken. Maar in principe zou ik altijd met een whitelist werken.

Nu kan iemand via wat creatieve url's aanroepen jouw server een hackpoging laten doen op andermans server. Dan ben jij in 1e instantie aansprakelijk
Ik wil dus juist voorkomen dat iemand 'creatieve urls' kan invoeren. Die aansprakelijkheid is wel een goed punt, daar had ik nog niet over nagedacht.

Ik ga het sowieso limiteren aan 1 request per IP per 3 seconden, al is het maar om mijn eigen server niet te zwaar te belasten.

Over RSS en andere diensten; deze app maak ik juist voor pagina's die dergelijke functionaliteit niet bieden. Zoals de iBood hunt pagina ;)

TabCinema : NiftySplit

Pagina: 1