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

Как обнаружить поддельных пользователей (сканеров) и cURL

Некоторые другие сайты используют cURL и поддельный HTTP-референт для копирования содержимого моего сайта. У нас есть какой-либо способ обнаружить cURL или не настоящий веб-браузер?

4b9b3361

Ответ 1

Нет никакого волшебного решения, чтобы избежать автоматического сканирования. Каждый человек может сделать, робот тоже может это сделать. Есть только решения, чтобы сделать работу более трудной, настолько трудной, что только сильные опытные вундеркинды могут попытаться передать их.

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

Я даю вам несколько примеров защит, которые вы можете попробовать.


Сеансы на IP

Если пользователь каждую минуту использует 50 новых сеансов, вы можете подумать, что этот пользователь может быть искателем, который не обрабатывает файлы cookie. Конечно, завиток отлично управляет куки, но если вы связываете его с счетчиком посещений за сеанс (объясняется позже) или если ваш искатель является noobie с вопросами cookie, он может быть эффективным.

Трудно представить, что 50 человек из одной и той же общей связи получат одновременную работу на вашем сайте (это, конечно, зависит от вашего трафика, это зависит от вас). И если это произойдет, вы можете заблокировать страницы своего веб-сайта, пока не будет заполнена captcha.

Идея:

1) вы создаете 2 таблицы: 1 для сохранения запрещенных ips и 1 для сохранения ip и сеансов

create table if not exists sessions_per_ip (
  ip int unsigned,
  session_id varchar(32),
  creation timestamp default current_timestamp,
  primary key(ip, session_id)
);

create table if not exists banned_ips (
  ip int unsigned,
  creation timestamp default current_timestamp,
  primary key(ip)
);

2) в начале вашего script, вы удаляете слишком старые записи из обеих таблиц

3) Далее вы проверяете, запрещен ли ip вашего пользователя или нет (вы установили флаг в true)

4) Если нет, вы считаете, сколько у него сеансов для его ip

5), если у него слишком много сеансов, вы вставляете его в свою запрещенную таблицу и устанавливаете флаг

6) вы вставляете свой ip в сеансы на таблицу ip, если он еще не вставлен

Я написал образец кода, чтобы лучше показать мою идею.

<?php

try
{

    // Some configuration (small values for demo)
    $max_sessions = 5; // 5 sessions/ip simultaneousely allowed
    $check_duration = 30; // 30 secs max lifetime of an ip on the sessions_per_ip table
    $lock_duration = 60; // time to lock your website for this ip if max_sessions is reached

    // Mysql connection
    require_once("config.php");
    $dbh = new PDO("mysql:host={$host};dbname={$base}", $user, $password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Delete old entries in tables
    $query = "delete from sessions_per_ip where timestampdiff(second, creation, now()) > {$check_duration}";
    $dbh->exec($query);

    $query = "delete from banned_ips where timestampdiff(second, creation, now()) > {$lock_duration}";
    $dbh->exec($query);

    // Get useful info attached to our user...
    session_start();
    $ip = ip2long($_SERVER['REMOTE_ADDR']);
    $session_id = session_id();

    // Check if IP is already banned
    $banned = false;
    $count = $dbh->query("select count(*) from banned_ips where ip = '{$ip}'")->fetchColumn();
    if ($count > 0)
    {
        $banned = true;
    }
    else
    {
        // Count entries in our db for this ip
        $query = "select count(*)  from sessions_per_ip where ip = '{$ip}'";
        $count = $dbh->query($query)->fetchColumn();
        if ($count >= $max_sessions)
        {
            // Lock website for this ip
            $query = "insert ignore into banned_ips ( ip ) values ( '{$ip}' )";
            $dbh->exec($query);
            $banned = true;
        }

        // Insert a new entry on our db if user session is not already recorded
        $query = "insert ignore into sessions_per_ip ( ip, session_id ) values ('{$ip}', '{$session_id}')";
        $dbh->exec($query);
    }

    // At this point you have a $banned if your user is banned or not.
    // The following code will allow us to test it...

    // We do not display anything now because we'll play with sessions :
    // to make the demo more readable I prefer going step by step like
    // this.
    ob_start();

    // Displays your current sessions
    echo "Your current sessions keys are : <br/>";
    $query = "select session_id from sessions_per_ip where ip = '{$ip}'";
    foreach ($dbh->query($query) as $row) {
        echo "{$row['session_id']}<br/>";
    }

    // Display and handle a way to create new sessions
    echo str_repeat('<br/>', 2);
    echo '<a href="' . basename(__FILE__) . '?new=1">Create a new session / reload</a>';
    if (isset($_GET['new']))
    {
        session_regenerate_id();
        session_destroy();
        header("Location: " . basename(__FILE__));
        die();
    }

    // Display if you're banned or not
    echo str_repeat('<br/>', 2);
    if ($banned)
    {
        echo '<span style="color:red;">You are banned: wait 60secs to be unbanned... a captcha must be more friendly of course!</span>';
        echo '<br/>';
        echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
    }
    else
    {
        echo '<span style="color:blue;">You are not banned!</span>';
        echo '<br/>';
        echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
    }
    ob_end_flush();
}
catch (PDOException $e)
{
    /*echo*/ $e->getMessage();
}

?>

Посетите счетчик

Если ваш пользователь использует тот же файл cookie для сканирования ваших страниц, вы сможете использовать его сеанс для его блокировки. Эта идея довольно проста: возможно ли, что ваш пользователь посещает 60 страниц за 60 секунд?

Идея:

  • Создайте массив в сеансе пользователя, он будет содержать время посещения() s.
  • Удаление посещений старше X секунд в этом массиве
  • Добавить новую запись для фактического посещения
  • Подсчитать записи в этом массиве
  • Запретить вашему пользователю, если он посетил страницы Y

Пример кода:

<?php

$visit_counter_pages = 5; // maximum number of pages to load
$visit_counter_secs = 10; // maximum amount of time before cleaning visits

session_start();

// initialize an array for our visit counter
if (array_key_exists('visit_counter', $_SESSION) == false)
{
    $_SESSION['visit_counter'] = array();
}

// clean old visits
foreach ($_SESSION['visit_counter'] as $key => $time)
{
    if ((time() - $time) > $visit_counter_secs) {
        unset($_SESSION['visit_counter'][$key]);
    }
}

// we add the current visit into our array
$_SESSION['visit_counter'][] = time();

// check if user has reached limit of visited pages
$banned = false;
if (count($_SESSION['visit_counter']) > $visit_counter_pages)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
$count = count($_SESSION['visit_counter']);
echo "You visited {$count} pages.";
echo str_repeat('<br/>', 2);

echo <<< EOT

<a id="reload" href="#">Reload</a>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

echo str_repeat('<br/>', 2);

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned! Wait for a short while (10 secs in this demo)...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}
?>

Изображение для загрузки

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

Эта идея (я думаю, самая элегантная и самая простая в использовании) использует mod_rewrite, чтобы скрыть код в .jpg/.png/... файл изображения. Это изображение должно быть доступно на каждой странице, которую вы хотите защитить: это может быть ваш логотип, но вы можете выбрать изображение небольшого размера (потому что это изображение нельзя кэшировать).

Идея:

1/Добавьте эти строки в ваш .htaccess

RewriteEngine On
RewriteBase /tests/anticrawl/
RewriteRule ^logo\.jpg$ logo.php

2/Создайте свой логотип .php с защитой

<?php

// start session and reset counter
session_start();
$_SESSION['no_logo_count'] = 0;

// forces image to reload next time
header("Cache-Control: no-store, no-cache, must-revalidate");

// displays image
header("Content-type: image/jpg");
readfile("logo.jpg");
die();

3/Увеличьте свой no_logo_count на каждой странице, чтобы добавить безопасность, и проверьте, достиг ли он вашего предела.

Пример кода:

<?php

$no_logo_limit = 5; // number of allowd pages without logo

// start session and initialize
session_start();
if (array_key_exists('no_logo_count', $_SESSION) == false)
{
    $_SESSION['no_logo_count'] = 0;
}
else
{
    $_SESSION['no_logo_count']++;
}

// check if user has reached limit of "undownloaded image"
$banned = false;
if ($_SESSION['no_logo_count'] >= $no_logo_limit)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
echo "You did not loaded image {$_SESSION['no_logo_count']} times.";
echo str_repeat('<br/>', 2);

// Display "reload" link
echo <<< EOT

<a id="reload" href="#">Reload</a>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

echo str_repeat('<br/>', 2);

// Display "show image" link : note that we're using .jpg file
echo <<< EOT

<div id="image_container">
    <a id="image_load" href="#">Load image</a>
</div>
<br/>

<script type="text/javascript">

  // On your implementation, you'llO of course use <img src="logo.jpg" />
  $('#image_load').click(function(e) {
    e.preventDefault();
    $('#image_load').html('<img src="logo.jpg" />');
  });

</script>

EOT;

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned: click on "load image" and reload...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}
?>

Проверка файлов cookie

Вы можете создавать файлы cookie на стороне javascript, чтобы проверить, не интерпретируют ли ваши пользователи javascript (например, искатель, использующий Curl, не работает).

Идея довольно проста: это примерно то же, что и проверка изображения.

  • Установите значение $_SESSION в 1 и увеличивайте его в каждом посещении.
  • если cookie (установленный в JavaScript) существует, установите значение сеанса 0
  • если это значение достигло предела, запретите пользователю

Код:

<?php

$no_cookie_limit = 5; // number of allowd pages without cookie set check

// Start session and reset counter
session_start();

if (array_key_exists('cookie_check_count', $_SESSION) == false)
{
    $_SESSION['cookie_check_count'] = 0;
}

// Initializes cookie (note: rename it to a more discrete name of course) or check cookie value
if ((array_key_exists('cookie_check', $_COOKIE) == false) || ($_COOKIE['cookie_check'] != 42))
{
    // Cookie does not exist or is incorrect...
    $_SESSION['cookie_check_count']++;
}
else
{
    // Cookie is properly set so we reset counter
    $_SESSION['cookie_check_count'] = 0;
}

// Check if user has reached limit of "cookie check"
$banned = false;
if ($_SESSION['cookie_check_count'] >= $no_cookie_limit)
{
    // puts ip of our user on the same "banned table" as earlier...
    $banned = true;
}

// At this point you have a $banned if your user is banned or not.
// The following code will allow us to test it...

echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';

// Display counter
echo "Cookie check failed {$_SESSION['cookie_check_count']} times.";
echo str_repeat('<br/>', 2);

// Display "reload" link
echo <<< EOT

<br/>
<a id="reload" href="#">Reload</a>
<br/>

<script type="text/javascript">

  $('#reload').click(function(e) {
    e.preventDefault();
    window.location.reload();
  });

</script>

EOT;

// Display "set cookie" link
echo <<< EOT

<br/>
<a id="cookie_link" href="#">Set cookie</a>
<br/>

<script type="text/javascript">

  // On your implementation, you'll of course put the cookie set on a $(document).ready()
  $('#cookie_link').click(function(e) {
    e.preventDefault();
    var expires = new Date();
    expires.setTime(new Date().getTime() + 3600000);
    document.cookie="cookie_check=42;expires=" + expires.toGMTString();
  });

</script>
EOT;


// Display "unset cookie" link
echo <<< EOT

<br/>
<a id="unset_cookie" href="#">Unset cookie</a>
<br/>

<script type="text/javascript">

  // On your implementation, you'll of course put the cookie set on a $(document).ready()
  $('#unset_cookie').click(function(e) {
    e.preventDefault();
    document.cookie="cookie_check=;expires=Thu, 01 Jan 1970 00:00:01 GMT";
  });

</script>
EOT;

// Display if you're banned or not
echo str_repeat('<br/>', 2);
if ($banned)
{
    echo '<span style="color:red;">You are banned: click on "Set cookie" and reload...</span>';
    echo '<br/>';
    echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png" />';
}
else
{
    echo '<span style="color:blue;">You are not banned!</span>';
    echo '<br/>';
    echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png" />';
}

Защита от прокси-серверов

Несколько слов о различных типах прокси, которые мы можем найти по сети:

  • "Обычный" прокси отображает информацию о подключении пользователя (в частности, его IP)
  • Анонимный прокси не отображает IP, но дает информацию об использовании прокси-сервера в заголовке.
  • Высоко-анонимный прокси не отображает пользовательский IP-адрес и не отображает информацию, которую браузер не может отправить.

Легко найти прокси для подключения любого веб-сайта, но очень сложно найти высоко-анонимных прокси.

Некоторые переменные $_SERVER могут содержать ключи, особенно если ваши пользователи находятся за прокси (исчерпывающий список из этого вопроса):

  • CLIENT_IP
  • FORWARDED
  • FORWARDED_FOR
  • FORWARDED_FOR_IP
  • HTTP_CLIENT_IP
  • HTTP_FORWARDED
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED_FOR_IP
  • HTTP_PC_REMOTE_ADDR
  • HTTP_PROXY_CONNECTION
  • HTTP_VIA
  • HTTP_X_FORWARDED
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED_FOR_IP
  • HTTP_X_IMFORWARDS
  • HTTP_XROXY_CONNECTION
  • VIA
  • X_FORWARDED
  • X_FORWARDED_FOR

Если вы обнаружите один из этих ключей в своей переменной $_SERVER, вы можете указать другое поведение (нижние пределы и т.д.) на свои антиспаллинговые ценные бумаги.


Заключение

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

Ответ 2

Помните: HTTP не волшебный. Существует определенный набор заголовков, отправленных с каждым HTTP-запросом; если эти заголовки отправляются веб-браузером, их также можно отправить любой программой - включая cURL (и libcurl).

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

UPDATE: Как правильно заметил unr3al011, curl не выполняет JavaScript, поэтому теоретически можно создать страницу, которая будет вести себя по-разному, если ее будут рассматривать grabbers (например, с настройкой и, позже, проверяя конкретный файл cookie средствами JS).

Тем не менее, это была бы очень хрупкая защита. Данные страницы все равно должны были быть захвачены с сервера - и этот HTTP-запрос (и он всегда HTTP-запрос) может быть эмулирован с помощью curl. Проверьте этот ответ, например, как победить такую ​​защиту.

... и я даже не упоминал, что некоторые грабители могут выполнять JavaScript. )

Ответ 3

Способом избежать поддельных ссылок является отслеживание пользователя

Вы можете отслеживать пользователя одним или несколькими из следующих способов:

  • Сохраните файл cookie в браузере с некоторым специальным кодом (например: последний URL-адрес, отметка времени) и проверьте его в каждом ответе вашего сервера.

  • Как и раньше, но используя сеансы вместо явных cookie

Для файлов cookie вы должны добавить криптографическую безопасность, например.

[Cookie]
url => http://someurl/
hash => dsafdshfdslajfd

hash вычисляется в PHP таким образом

$url = $_COOKIE['url'];
$hash = $_COOKIE['hash'];
$secret = 'This is a fixed secret in the code of your application';

$isValidCookie = (hash('algo', $secret . $url) === $hash);

$isValidReferer = $isValidCookie & ($_SERVER['HTTP_REFERER'] === $url)

Ответ 4

Как уже отмечалось, cURL не может выполнить JavaScritp (насколько мне известно), поэтому вы можете попытаться настроить someting up, например raina77ow, но это не будет wokrk для других захватчиков/донгрудеров.

Я предлагаю вам создать ловушку бота, чтобы вы справлялись с захватчиками/загрузчиками, которые могут выполнять JavaScript.

Я не знаю ни одного решения, чтобы полностью предотвратить это, поэтому моя лучшая рекомендация - попробовать несколько решений:

1) позволяют только известные пользовательские агенты, такие как все основные браузеры, в вашем файле .htaccess

2) Настройте свой robots.txt для предотвращения ботов

3) Настройте ловушку бота для ботов, которые не уважают файл robots.txt

Ответ 5

поместите это в корневую папку как .htaccess файл. это может помочь. Я нашел его на одном веб-сайте провайдера хостинга, но не знаю, что это значит.

SetEnvIf User-Agent ^Teleport graber   
SetEnvIf User-Agent ^w3m graber    
SetEnvIf User-Agent ^Offline graber   
SetEnvIf User-Agent Downloader graber  
SetEnvIf User-Agent snake graber  
SetEnvIf User-Agent Xenu graber   
Deny from env=graber