PHP CURL script with CSRF support



  • I wanted to use a script I found to show my RRD graphs to the public. I found a nice PHP script, but it was pre2.0 so it didn't work.

    CSRF was a royal pain to get working, but I managed.

    I took this script here: http://captain-slow.dk/2010/09/24/public-rrd-graphs-from-pfsense/

    graph_rrd.php

    
    require_once("config.inc.php");
    if (isset($_GET["file"]) && isset($_GET["interval"]))
    {
            //Get CSRF
    
            $ckfile = tempnam ("/tmp", "CURLCOOKIE");
            $curl_handle = curl_init();
            curl_setopt($curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12");
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt ($curl_handle, CURLOPT_COOKIEJAR, $ckfile);
            curl_setopt ($curl_handle, CURLOPT_COOKIEFILE, $ckfile);
            curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($curl_handle, CURLOPT_HEADER, 1);
            curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
            curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($curl_handle,CURLOPT_URL, $pfsenseprot . "://" . $pfsenseip . "/index.php");
    
            $buffer = curl_exec($curl_handle);
    
            $csrf = substr($buffer, strpos($buffer,'sid:') , 110);
    
            //Login
    
            $post = array(
                    '__csrf_magic' => $csrf,
                    'login' => urlencode('Login'),
                    'usernamefld' => urlencode($username),
                    'passwordfld' => urlencode($password)
            );
    
            $post_string = "";
            foreach($post as $key=>$value) { $post_string .= $key.'='.$value.'&'; }
    
            rtrim($post_string, '&');
    
            $curl_handle = curl_init();
            curl_setopt($curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12");
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($curl_handle,CURLOPT_POST, count($post));
            curl_setopt($curl_handle,CURLOPT_POSTFIELDS, $post_string);
            curl_setopt ($curl_handle, CURLOPT_COOKIEJAR, $ckfile);
            curl_setopt ($curl_handle, CURLOPT_COOKIEFILE, $ckfile);
            curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($curl_handle, CURLOPT_HEADER, 1);
            curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
            curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($curl_handle,CURLOPT_URL, $pfsenseprot . "://" . $pfsenseip . "/index.php");
    
            $buffer = curl_exec($curl_handle);
    
            //Get PNG
    
            $end = time();
            $start = time() - $_GET["interval"];
    
            $curl_handle = curl_init();
            curl_setopt($curl_handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.12) Gecko/20070508 Firefox/1.5.0.12");
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($curl_handle, CURLOPT_USERPWD, $username . ":" . $password);
            curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
            curl_setopt($curl_handle, CURLOPT_COOKIEFILE, $ckfile);
            curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($curl_handle,CURLOPT_URL, $pfsenseprot . "://" . $pfsenseip . "/status_rrd_graph_img.php?start=" . $start  . "&end=" . $end . "&database=" . $_GET["file"] . "&style=inverse");
    
            $buffer = curl_exec($curl_handle);
    
            if(curl_errno($curl_handle))
            {
                    echo 'Curl error: ' . curl_error($curl_handle);
            }
            else
            {
                    if (empty($buffer))
                    {
                            print "No picture avalible.";
                    }
                    else
                    {
                            header('Content-Type: image/png');
                            print $buffer;
                    }
            }
    
            curl_close($curl_handle);
    }
    ?>
    

    config.inc.php
    Change the variables in here to match you config.
    Don't forget to put in your default gateway name where it says [GATEWAY]
    Easy way to set this is to goto the RRD quality page, and copy in image url for the graph.
    You will find the .rrd line in the url.

    
            $username = "admin";            //username for pfSense
            $password = "password";            //password for pfSense
            $pfsenseip = "10.0.0.1";        //ip of pfSense
            $pfsenseprot = "http";          //http or https
    
            $refresh = 30;                  //Seconds between reload of the image
    
            $scale = array(
                            0 => array("14400", "4 Hours", 30),
                            1 => array("57600", "16 Hours", 30),
                            2 => array("172800", "2 Days", 180),
                            3 => array("2764800", "1 Month", 180),
                            4 => array("16588800", "6 Months", 180),
                            5 => array("33177600", "1 Year", 180)
                           );
    
            $graphs = array(
                            0 => array("wan-traffic.rrd", "WAN :: Traffic"),
                            1 => array("wan-packets.rrd", "WAN :: Packets"),
                            2 => array("[GATEWAY]-quality.rrd", "WAN :: Quality"),
                            3 => array("system-processor.rrd", "System :: Processor ")
                           );
    ?>
    
    

    index.php

    
    require_once("functions.php");
    require_once("config.inc.php");
    
    if (!isset($_GET["type"]) || !isset($_GET["interval"]))
    {
            header('Location: ?type=' . $graphs[0][0] . '&interval=' . $scale[0][0]) ;
    }
    
    ?>
    
                    <title>pfSense stats @ <?php print $_SERVER['HTTP_HOST'] ?></title>
    
                            ![](http://i.imgur.com/SqctVVa.jpg)
    
    print "[ ";
    
    for ($i = 0; $i < count($graphs); $i++)
    {
            $graphs = $GLOBALS['graphs'];
            $num = count($graphs);
            if ($num-1 == $i)
            {
                    print "[" . $graphs[$i][1] . "](?" . url("type", $graphs[$i][0]) . ") ]";
            }
            else
            {
                    print "[" . $graphs[$i][1] . "](?" . url("type", $graphs[$i][0]) . ") | ";
            }
    }
    
    print "
    
    [ ";
    
    for ($i = 0; $i < count($scale); $i++)
    {
            $scale = $GLOBALS['scale'];
            $num = count($scale);
            if ($num-1 == $i)
            {
                    print "[" . $scale[$i][1] . "](?" . url("interval", $scale[$i][0]) . ") ]";
            }
            else
            {
                    print "[" . $scale[$i][1] . "](?" . url("interval", $scale[$i][0]) . ") | ";
            }
    
            if ($scale[$i][0] == $_GET["interval"])
            {
                    $refresh = $scale[$i][2];
            }
    }
    ?>                      
    
                                    ![](graph_rrd.php?file=<?php print $_GET[)&interval=" name="refresh">
    
                            [pfSense stats by bld @ bld.is-a-geek.com](http://bld.is-a-geek.com/2010/09/24/public-rrd-graphs-from-pfsense/)
                            [pfSense 2.0 edit by ionstorm66](https://forum.pfsense.org/index.php/topic,72558.0.html)
    
    

    functions.php

    
    function url($q="empty", $value="empty")
    {
            $output = $_SERVER['QUERY_STRING'];
            if ($q != "empty" && $value != "empty")
            {
                    if (strlen($output))
                    {
                            $temp = explode("&", $output);
    
                            for($i = 0; $i < count($temp); $i++)
                            {
                                    $subtemp = explode("=", $temp[$i]);
                                    if ($subtemp[0] == $q)
                                    {
                                            $output = str_replace($subtemp[0] . "=" . $subtemp[1], $subtemp[0] . "=" . $value, $output);
                                    }
                            }
                    }
            }
            return $output;
    }
    ?>
    
    

    style.css

    
    html, body
    {
        height: 100%;
    }
    
    body
    {
            margin: 0;
            padding: 0;
            background-color: #b0c4de; font-family: serif; font-size: 14px; font-weight: normal;
    }
    
    A
    {
            font-family:serif; font-size: 14px; font-weight: bold; text-decoration: underline; color: #000000;
    }
    
    A:Visited
    {
            font-family:serif; font-size: 14px; font-weight: bold; text-decoration: underline; color: #000000;
    }
    
    A:Hover
    {
            font-family:serif; font-size: 14px; font-weight: bold; text-decoration: underline; color: #FFFFFF;
    }
    
    #top
    {
            position: absolute;
    }
    
    #container
    {
            min-height: 100%;
            margin-bottom: -20px;
    }
    
    * html #container
    {
            height: 100%;
    }
    
    #footer-spacer
    {
            height: 20px;
    }
    
    #footer
    {
            border-top: 1px solid #000;
            height: 19x;
    }
    
    


  • Is this script outdated or am i doing some thing wrong that dont get it to work?
    Running 2.1.5-RELEASE (amd64)
    http://familjenbjornsson.se/stats



  • $csrf = substr($buffer, strpos($buffer,'sid:') , 110);

    Actually needs to be $csrf = substr($buffer, strpos($buffer,'sid:') , 55); in order to get the csrf token working.
    This is because the token length is 55.


Log in to reply