Подтвердить что ты не робот

Получение HTML-страницы веб-сайта с использованием cURL с текущими данными сеанса и файлов cookie на защищенной странице

Вопрос полностью пересмотрен: 19 февраля

То, что я хочу (короче):

Я хотел бы получить HTML-страницу, используя cURL, которая защищена логином пользователя (во время запроса cURL пользователь вошел в систему с правами на страницу).

Подробнее:

Ситуация заключается в том, что пользователь находится на веб-странице, такой как index.php?w=2344&y=lalala&x=something, которая защищена (по безопасности script class.Firewizz.Security.php). На этой странице есть кнопка "print as pdf". Это отправляет пользователя на страницу getPDF.php, на этой странице отображается, откуда идет запрос, и получает эту страницу с использованием cURL, и этот вывод будет отправляться в браузер в виде PDF-печати. ​​

Но теперь я устанавливаю переменную страницы static на странице getPDF.php, чтобы она не проверяла реферер, и я на 100% уверен, что страница, которую она пытается получить, верна.

Кроме того, вывод просто эхом, как есть и еще не преобразован в PDF, чтобы он не мешал проблеме.

Ожидаемый результат теперь такой же, как если бы пользователь перешел на страницу. за исключением того, что это не так, пользователь ничего не получает.

Что мы знаем? Мы знаем, что данные $_SESSION НЕ отправляются в cURL, я знаю это для факта, потому что я выбрал данные $_SESSION в выходном файле, который говорит, что они пусты.

После многих попыток у нас по-прежнему нет решения, что когда-либо, все еще нет данных $_SESSION.

Я не хочу компрометировать безопасность script любым способом, поэтому решение "remove ini_set('session.use_only_cookies', 1); НЕ является тем, что я ищу".

По запросу (для тех, которые предназначены для помощи) я могу отправить полные файлы script, но я опубликую соответствующие фрагменты ниже.

class.Firewizz.Security.php

<?php

/*
 * Firewizz UserLogin
 */

namespace Firewizz;



class Security
{

     // Start the session, with Cookie data
    public function Start_Secure_Session()
    {
        // Forces sessions to only use cookies.
        ini_set('session.use_only_cookies', 1);

        // Gets current cookies params
        $cookieParams = session_get_cookie_params();

        // Set Cookie Params
        session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $this->isHTTPS, $this->deny_java_session_id);
        // Sets the session name
        session_name($this->session_name);

        // Start the php session
        session_start();

        // If new session or expired, generate new id
        if (!isset($_SESSION['new_session']))
        {
            $_SESSION['new_session'] = "true";

            // regenerate the session, delete the old one.
            session_regenerate_id(true);
        }
    }

    // Check of user is logged in to current session, return true or false;
    public function LOGGED_IN()
    {
        return $this->_login_check();
    }

    public function LOGOUT()
    {
    // Unset all session values
        $_SESSION = array();

        // get session parameters
        $params = session_get_cookie_params();

        // Delete the actual cookie.
        setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
        // Destroy session
        session_destroy();
        if (!headers_sent())
        {
            header("Location: " . $this->login_string, true);
        }
        else
        {
            echo '<script>window.location="/"</script>';
        }
    }

    // Must pass variables or send to login page!
    public function BORDER_PATROL($user_has_to_be_logged_in, $page_loaded_from_index)
    {
        $pass_border_partrol = true;

        if (!$this->LOGGED_IN() && $user_has_to_be_logged_in)
        {
            $pass_border_partrol = false;
        }
        if (filter_input(INPUT_SERVER, "PHP_SELF") != "/index.php" && $page_loaded_from_index)
        {
            $pass_border_partrol = false;
        }

        // Kick to login on fail
        if (!$pass_border_partrol)
        {
            $this->LOGOUT();
            exit();
        }

    }

    // Catch login, returns fail string or false if no errors
    public function CATCH_LOGIN()
    {
        if (filter_input(INPUT_POST, "id") == "login" && filter_input(INPUT_POST, "Verzenden") == "Verzenden")
        {
            // Variables from form.
            $email = filter_input(INPUT_POST, "email");
            $sha512Pass = filter_input(INPUT_POST, "p");

            // Database variables
            $db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);

            // Prepage sql
            if ($stmt = $db_accounts->prepare("SELECT account_id, verified, blocked ,login_email, login_password, login_salt, user_voornaam, user_tussenvoegsel, user_achternaam FROM accounts WHERE login_email = ? LIMIT 1"))
            {
                $stmt->bind_param('s', $email); // Bind "$email" to parameter.
                $stmt->execute(); // Execute the prepared query.
                $stmt->store_result();

                $stmt->bind_result($user_id, $verified, $blocked, $email, $db_password, $salt, $voornaam, $tussenvoegsel, $achternaam); // get variables from result.

                $stmt->fetch();
                $password = hash('sha512', $sha512Pass . $salt); // hash the password with the unique salt.
                $tussen = ' ';
                if ($tussenvoegsel != "")
                {
                    $tussen = " " . $tussenvoegsel . " ";
                }
                $username = $voornaam . $tussen . $achternaam;



                if ($stmt->num_rows == 1)
                { // If the user exists
                    // Check blocked
                    if ($blocked == "1")
                    {
                        return 'Deze acount is geblokkeerd, neem contact met ons op.';
                    }

                    // We check if the account is locked from too many login attempts
                    if ($this->_checkBrute($user_id, $db_accounts) == true)
                    {
                        // Account is locked
                        // Send an email to user saying their account is locked
                        return "Te vaak fout ingelogd,<br />uw account is voor " . $this->blockout_time . " minuten geblokkerd.";
                    }
                    else
                    {
                        if ($db_password == $password && $verified == 1)
                        {
                            // Password is correct!, update lastLogin
                            if ($stmt = $db_accounts->prepare("UPDATE accounts SET date_lastLogin=? WHERE account_id=?"))
                            {
                                $lastlogin = date("Y-m-d H:i:s");

                                $stmt->bind_param('ss', $lastlogin, $user_id); // Bind "$email" to parameter.
                                $stmt->execute();
                                $stmt->close();
                            }

                            $ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
                            $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

                            $user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
                            $_SESSION['user_id'] = $user_id;
                            $username = $username; // XSS protection as we might print this value
                            $_SESSION['username'] = $username;
                            $_SESSION['login_string'] = hash('sha512', $password . $ip_address . $user_browser);
                            // Login successful.

                            if ($this->MailOnLogin != FALSE)
                            {
                                mail($this->MailOnLogin, 'SECUREPLAY - LOGIN', $username . ' logged in to the secureplay platform..');
                            }
                            return false;
                        }
                        else
                        {
                            // Password is not correct
                            // We record this attempt in the database
                            $now = time();
                            $db_accounts->query("INSERT INTO login_attempts (userID, timestamp) VALUES (" . $user_id . ", " . $now . ")");

                            return "Onbekende gebruikersnaam en/of wachtwoord.";
                        }
                    }
                }
                else
                {
                    return "Onbekende gebruikersnaam en/of wachtwoord.";
                }
            }
            else
            {
                return 'SQL FAIL! ' . mysqli_error($db_accounts);
            }
            return "Onbekende fout!";
        }


        return false;
    }

    private function _checkBrute($user_id, $db_accounts)
    {
        // Get timestamp of current time
        $now = time();
        // All login attempts are counted from the past 2 hours.
        $valid_attempts = $now - ($this->blockout_time * 60);

        if ($stmt = $db_accounts->prepare("SELECT timestamp FROM login_attempts WHERE userID = ? AND timestamp > $valid_attempts"))
        {
            $stmt->bind_param('i', $user_id);
            // Execute the prepared query.
            $stmt->execute();
            $stmt->store_result();
            // If there has been more than 5 failed logins
            if ($stmt->num_rows > $this->max_login_fails)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return true;
        }
    }

    // Login Check if user is logged in correctly
    private function _login_check()
    {
        // Database variables
        $db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);

        // Check if all session variables are set
        if (isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string']))
        {
            $user_id = $_SESSION['user_id'];
            $login_string = $_SESSION['login_string'];
            $username = $_SESSION['username'];
            $ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
            $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

            if ($stmt = $db_accounts->prepare("SELECT login_password FROM accounts WHERE account_id = ? LIMIT 1"))
            {
                $stmt->bind_param('i', $user_id); // Bind "$user_id" to parameter.
                $stmt->execute(); // Execute the prepared query.
                $stmt->store_result();

                if ($stmt->num_rows == 1)
                { // If the user exists
                    $stmt->bind_result($password); // get variables from result.
                    $stmt->fetch();
                    $login_check = hash('sha512', $password . $ip_address . $user_browser);
                    if ($login_check == $login_string)
                    {
                        // Logged In!!!!
                        return $user_id;
                    }
                    else
                    {
                        // Not logged in
                        return false;
                    }
                }
                else
                {
                    // Not logged in
                    return false;
                }
            }
            else
            {
                // Not logged in
                //die("f3");
                return false;
            }
        }
        else
        {
            // Not logged in
            return false;
        }
    }

}

secured_page

<?php
require_once 'assets/class.Firewizz.Security.php';

if (!isset($SECURITY))
{
    $SECURITY = new Firewizz\Security();
}

// Check if user is logged in or redirect to login page;
$SECURITY->BORDER_PATROL(true, true);


// CONTENT bla bla

?>

getPDF.php

<?php
// Requires
require_once 'assets/class.FirePDF.php';
require_once 'assets/class.Firewizz.Security.php';
$SECURITY = new \Firewizz\Security();
$SECURITY->Start_Secure_Session();

// Html file to scrape, if this works replace with referer so the page that does the request gets printed.(prepend by security so it can only be done from securePlay
$html_file = 'http://www.website.nl/?p=overzichten&sort=someSort&s=67';

// Output pdf filename
$pdf_fileName = 'Test_Pdf.pdf';

/*
 * cURL part
 */

// create curl resource
$ch = curl_init();

// set source url
curl_setopt($ch, CURLOPT_URL, $html_file);

// set cookies
$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . ";";

// set cURL Options
$tmp = tempnam("/tmp", "CURLCOOKIE");
if ($tmp === FALSE)
{
    die('Could not generate a temporary cookie jar.');
}

$options = array(
    CURLOPT_RETURNTRANSFER => true, // return web page
    //CURLOPT_HEADER => true, //return headers in addition to content
    CURLOPT_ENCODING => "", // handle all encodings
    CURLOPT_AUTOREFERER => true, // set referer on redirect
    CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
    CURLOPT_TIMEOUT => 120, // timeout on response
    CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
    CURLINFO_HEADER_OUT => true,
    CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_COOKIEJAR => $tmp,
    //CURLOPT_COOKIEFILE => $tmp,
    CURLOPT_COOKIE => $cookiesIn
);

// $output contains the output string
curl_setopt_array($ch, $options);
$output = curl_exec($ch);

// close curl resource to free up system resources
curl_close($ch);

// output the cURL
echo $output;
?>

Как мы тестируем

Текущее тестирование выполняется путем входа пользователя в систему и перехода к правильной странице, которую мы хотим получить с помощью cURL, и проверки того, что он видит страницу (которая работает). Теперь мы запустим страницу getPDF.php на новой вкладке. в котором мы видим пустую страницу из-за сбоя безопасности. если добавить echo "session data:" . $_SESSION["login_string"]; в безопасности script мы видим, что переменные в $_SESSION пусты. Когда мы вставляем ту же строку в getPDF.php, мы видим, что она устанавливается там. Итак, мы знаем, что факт не был передан cURL.

Некоторая краткая информация.

  • Итак, с приведенным выше кодом мы получаем пустую страницу;
  • $_ SESSION данные не отправляются;
  • Довольно уверены, что файлы cookie не отправляются;
  • Пробовал различные настройки cURL, ни один из них не был успешным,
  • Было бы идеально, если бы были переданы данные ALL $_SESSION и $_COOKIE;
  • Пробовал все сказанное в комментариях или ответах.
4b9b3361

Ответ 1

Хорошо, он решен

После много исследований.

Данные cookie передаются, но это не делает данные сеанса. Это было исправлено с использованием следующего метода:

private function Cookie2Session($name)
{
    if (filter_input(INPUT_COOKIE, $name))
    {
        $_SESSION[$name] = filter_input(INPUT_COOKIE, $name);
    }
}

// following lines put within the BORDER_PATROL Method
if (filter_input(INPUT_COOKIE, 'pdfCurl'))
{
    $this->Cookie2Session('user_id');
    $this->Cookie2Session('username');
    $this->Cookie2Session('login_string');
    $this->Cookie2Session('REMOTE_ADDR');
    $this->Cookie2Session('HTTP_USER_AGENT');
    $_SESSION['new_session'] = "true";
}

Небольшое изменение метода _login_check()

// Login Check if user is logged in correctly
private function _login_check()
{
    // Database variables
    $db_accounts = mysqli_connect($this->mySQL_accounts_host, $this->mySQL_accounts_username, $this->mySQL_accounts_password, $this->mySQL_accounts_database);

    // Check if all session variables are set
    if (isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string']))
    {
        $user_id = $_SESSION['user_id'];
        $login_string = $_SESSION['login_string'];
        $username = $_SESSION['username'];
        $ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
        $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

// =====>> add this code, because cURL req comes from server. <<=====
        if (isset($_SESSION["REMOTE_ADDR"]) && ($_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR']))
        {
            $ip_address = $_SESSION["REMOTE_ADDR"];
        }

// {rest of code}

Небольшие обновления в файле getPHP.php:

<?php
// Requires
require_once 'assets/class.FirePDF.php';
require_once 'assets/class.Firewizz.Security.php';
$SECURITY = new \Firewizz\Security();
$SECURITY->Start_Secure_Session();

// Html file to scrape, if this works replace with referer so the page that does the request gets printed.(prepend by security so it can only be done from securePlay
$html_file = 'http://www.secureplay.nl/?p=overzichten&sort=SpeelplaatsInspecties&s=67';

// Output pdf filename
$pdf_fileName = 'Test_Pdf.pdf';

/*
 * cURL part
 */

// create curl resource
$ch = curl_init();

// set source url
curl_setopt($ch, CURLOPT_URL, $html_file);

// set cookies
$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . "; pdfCurl=true; REMOTE_ADDR=" . $_SERVER['REMOTE_ADDR'] . "; HTTP_USER_AGENT=" . $_SERVER['HTTP_USER_AGENT'];
$agent = $_SERVER['HTTP_USER_AGENT'];

// set cURL Options
$tmp = tempnam("/tmp", "CURLCOOKIE");
if ($tmp === FALSE)
{
    die('Could not generate a temporary cookie jar.');
}

$options = array(
    CURLOPT_RETURNTRANSFER => true, // return web page
    //CURLOPT_HEADER => true, //return headers in addition to content
    CURLOPT_ENCODING => "", // handle all encodings
    CURLOPT_AUTOREFERER => true, // set referer on redirect
    CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
    CURLOPT_TIMEOUT => 120, // timeout on response
    CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
    CURLINFO_HEADER_OUT => true,
    CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_COOKIEJAR => $tmp,
    //CURLOPT_COOKIEFILE => $tmp,
    CURLOPT_COOKIE => $cookiesIn,
    CURLOPT_USERAGENT => $agent
);

// $output contains the output string
curl_setopt_array($ch, $options);
$output = curl_exec($ch);

// close curl resource to free up system resources
curl_close($ch);

// output the cURL
echo $output;
?>

С помощью вышеуказанных знаний вы можете полностью использовать cURL, чтобы посещать защищенную страницу с текущими данными сеанса только с небольшими занятиями в вашей безопасности.

Ответ 2

Таким образом, ваш $cookiesIn должен определить ваши файлы cookie. Я приведу пример, основанный на ваших фрагментах кода:

$cookiesIn = "user_id=" . $_SESSION['user_id'] . "; username=" . $_SESSION['username'] . "; login_string=" . $_SESSION['login_string'] . ";";

Попробуйте установить это на странице pdfCreator. Замените $cookiesIn = ""; на строку выше и посмотрите, дает ли это другой результат.

Кроме того, здесь отличная ссылка для опции cURL cookie:

https://curl.haxx.se/libcurl/c/CURLOPT_COOKIE.html

Если вы хотите, чтобы все файлы cookie просто отправлялись вместо их назначения, используйте этот код:

$tmp = tempnam("/tmp", "CURLCOOKIE");
if($tmp === FALSE) die('Could not generate a temporary cookie jar.');

$options = array(
    CURLOPT_RETURNTRANSFER => true, // return web page
    //CURLOPT_HEADER => true, //return headers in addition to content
    CURLOPT_ENCODING => "", // handle all encodings
    CURLOPT_AUTOREFERER => true, // set referer on redirect
    CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
    CURLOPT_TIMEOUT => 120, // timeout on response
    CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
    CURLINFO_HEADER_OUT => true,
    CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_COOKIEJAR => $tmp,
    CURLOPT_COOKIEFILE => $tmp,
);

Этот код сбрасывает все текущие файлы cookie для использования в cURL с опцией COOKIEJAR. Затем, когда мы обозначаем COOKIEFILE, мы указываем, где cURL должен выглядеть так, чтобы включать куки с запросом.

Тем не менее, я избавился от ссылки $cookiesIn, поскольку она не нужна, если вы используете код выше.

Ответ 3

В этом случае, если алгоритм управления сеансом звучит, вы просто хотите изменить формат, в который была отправлена ​​страница.

Использование cURL для повторной выборки страницы - один из способов сделать это, но это похоже на проблему XY; вы фактически не хотите использовать cURL, вы хотите управлять выходным форматом, будь то HTML или PDF.

Одним из жизнеспособных вариантов было бы перезагрузить страницу после добавления определенного параметра, который будет введен в контекст страницы и изменить функцию вывода. Например, вы можете обернуть всю страницу в пузырь буферизации вывода:

// Security checks as usual, then:

if (array_key_exists('output', $_GET)) {
    $format = $_GET['output']; // e.g. "pdf"
    // We could check whether the response handler has a printAs<FORMAT> method
    switch ($format) {
        case 'pdf': $outputFn = 'printAsPDF'; break;
        default:
            throw new \Exception("Output in {$format} format not supported");
    }
    ob_start($output);
}
// Page is generated normally

Выход "printAsPDF" получит содержимое страницы и будет использовать что-то вроде dompdf или wkhtml2pdf, чтобы отформатировать его как файл PDF, добавить соответствующие заголовки Content-Type и вернуть форматированный PDF файл.

Безопасность остается прежней, и модификация может быть фактически реализована на этапе декодирования запроса. Переменная состояния с текущим используемым форматом вывода может быть доступна для других объектов, что позволяет им вести себя по-разному в зависимости от ситуации (например, функция generateMenu() может сразу же вернуться, вместо того, чтобы показывать что-то, что не могло бы смысл в PDF).