619 lines
26 KiB
PHP
619 lines
26 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This is the endboard software, version beta 0.73
|
|
* It is a textboard written for the use in the darknets.
|
|
*
|
|
* This file holds all the functions used to deal with bots. It can be
|
|
* included without side effects.
|
|
*
|
|
* The writing of this code started some time ago with another software
|
|
* called smolBBS. Although there is almost no original code left now,
|
|
* I still regard endboard as a fork of smolBBS.
|
|
* The author of smolBBS has required that the following text be
|
|
* distributed with any redistribution, so here it goes.
|
|
* The license and other conditions apply to endboard as well.
|
|
*
|
|
* IRC: *dulm @ irc.rizon.net
|
|
*
|
|
* Copyright (C) 2020 sandlind
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* (1) Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* (2) Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* (3)The name of the author may not be used to
|
|
* endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
// checks if the bot trap has been called recently from the ip.
|
|
// according to the parameters in the config file, the request is then
|
|
// either granted or blocked.
|
|
// if the blocking of tor is enabled, 127.0.0.1 will be included in the
|
|
// blocking, which can mean that no connections from tor or local are taken
|
|
// during the block time.
|
|
function bot_block($db, $settings, $ip)
|
|
{
|
|
if ( ($settings['enable_bot_block'] != TRUE) ) {
|
|
return;
|
|
}
|
|
|
|
if ( ($settings['enable_tor_block'] != TRUE)
|
|
&& ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') ) {
|
|
return;
|
|
}
|
|
|
|
$current = time();
|
|
$max_age = $current - ($settings['block_time'] * 60);
|
|
// max age is in minutes, so times 60 to go to seconds
|
|
|
|
if ($settings['superstrict_block'] == TRUE) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'bot'
|
|
AND ip = '$ip'
|
|
AND event in ('Level 2',
|
|
'Level 1',
|
|
'429')
|
|
AND unix_timestamp > '$max_age'");
|
|
} else {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'bot'
|
|
AND ip = '$ip'
|
|
AND event in ('Level 2',
|
|
'Level 1')
|
|
AND unix_timestamp > '$max_age'");
|
|
}
|
|
|
|
$result = $statement->execute();
|
|
|
|
$trap_visits = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$trap_visits++;
|
|
}
|
|
|
|
if ( ($trap_visits > $settings['max_trap_visits']) ) {
|
|
$bot_block_message = '429';
|
|
log_event($db, $settings, 'bot', $bot_block_message, $ip);
|
|
header( 'HTTP/1.1 429 Too Many Requests' );
|
|
quit($db, '429');
|
|
}
|
|
|
|
if ( ($settings['max_landing'] > 0)
|
|
&& ($settings['superstrict_block'] == TRUE) ) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'bot'
|
|
AND ip = '$ip'
|
|
AND event in ('landing page bot request',
|
|
'429')
|
|
AND unix_timestamp > '$max_age'");
|
|
} elseif ( ($settings['max_landing'] > 0) ) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'bot'
|
|
AND ip = '$ip'
|
|
AND event = 'landing page bot request'
|
|
AND unix_timestamp > '$max_age'");
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
$result = $statement->execute();
|
|
|
|
$landing_visits = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$landing_visits++;
|
|
}
|
|
|
|
if ( ($landing_visits > $settings['max_landing']) ) {
|
|
$bot_block_message = '429';
|
|
log_event($db, $settings, 'bot', $bot_block_message, $ip);
|
|
header( 'HTTP/1.1 429 Too Many Requests' );
|
|
quit($db, '429');
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// receive a message from a bot, check if it's ok to post, and do it (or quit)
|
|
function bot_me($db, $settings)
|
|
{
|
|
|
|
$json_data = json_decode(file_get_contents('php://input'), TRUE);
|
|
|
|
if ( (empty($json_data['text'])) || (empty($json_data['sub'])) ) {
|
|
header( 'HTTP/1.1 400 Bad Request' );
|
|
quit($db,'400');
|
|
}
|
|
|
|
$sub = filter($json_data['sub'], 'alnum', $settings['max_name_sub']);
|
|
|
|
if (!in_array($sub, $settings['anonymous_bot_subs'])) {
|
|
if (!empty($json_data['key'])) {
|
|
$key = filter($json_data['key'], 'alnum', 20);
|
|
// 20 chars is enough for a bot key
|
|
if (!in_array($key, $settings['bot_keys'])) {
|
|
$auth_message = 'bot used wrong key';
|
|
log_event($db, $settings, 'auth', $auth_message, '');
|
|
sleep(10);
|
|
header( 'HTTP/1.1 401 Unauthorized' );
|
|
quit($db,'401');
|
|
}
|
|
} else {
|
|
header( 'HTTP/1.1 400 Bad Request' );
|
|
quit($db,'400');
|
|
}
|
|
}
|
|
|
|
if (!empty($json_data['org_id'])) {
|
|
$org_id = filter($json_data['org_id'], 'alnum',
|
|
$settings['max_name_sub']);
|
|
} else {
|
|
$org_id = '';
|
|
}
|
|
|
|
$text = strip_tags($json_data['text']);
|
|
check_spam($db, $text, $settings);
|
|
$text_id = hash('sha512', $text);
|
|
|
|
if ( (check_original_content
|
|
($db, $settings, $sub, $text_id, $org_id) == FALSE) ) {
|
|
header( 'HTTP/1.1 403 Forbidden' );
|
|
$content_message = 'This text has been posted before, the admin'
|
|
. ' requests original content.';
|
|
quit($db, $content_message);
|
|
}
|
|
|
|
make_post($db, $sub, $settings, $text, $org_id, '');
|
|
}
|
|
|
|
// check if the ip has already passed the portal, in this case return.
|
|
// if not, display a simple text and button to click to proceed.
|
|
// the page displayed is done with inline styling, so that no
|
|
// additional files will be requested.
|
|
// Update: what started with the checking of the ip, has now expanded to
|
|
// up to six parameters, which are concatenated and hashed.
|
|
function check_portal($db, $settings, $ip)
|
|
{
|
|
|
|
if ( ($settings['enable_portal'] != TRUE) ) {
|
|
return;
|
|
}
|
|
|
|
if ( ($settings['enable_portal_tor'] != TRUE)
|
|
&& ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') ) {
|
|
return;
|
|
}
|
|
|
|
$current = time();
|
|
$max_age = $current - ($settings['portal_lifetime'] * 60);
|
|
// lifetime is in minutes, so times 60 to go to seconds
|
|
|
|
if ($settings['auto_prolong_portal'] == TRUE) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'portal'
|
|
AND ip = '$ip'
|
|
AND event in ('pass',
|
|
'visit')
|
|
AND unix_timestamp > '$max_age'
|
|
ORDER BY ROWID DESC LIMIT 1");
|
|
} else {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'portal'
|
|
AND ip = '$ip'
|
|
AND event in ('pass')
|
|
AND unix_timestamp > '$max_age'
|
|
ORDER BY ROWID DESC LIMIT 1");
|
|
}
|
|
|
|
$result = $statement->execute();
|
|
|
|
$portal_pass = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$portal_pass++;
|
|
}
|
|
|
|
if ( ($portal_pass > 0) ) {
|
|
// bigger zero means we have the last hit, meaning the ip
|
|
// is known
|
|
$portal_message = 'visit';
|
|
log_event($db, $settings, "portal", $portal_message, $ip);
|
|
return;
|
|
} else {
|
|
$random_string = make_token(20, 'alpha');
|
|
|
|
// $request = '/' . $random_string;
|
|
|
|
$request = $_SERVER['REQUEST_URI'] . $random_string;
|
|
|
|
header( 'HTTP/1.1 202 Accepted' );
|
|
header( 'Cache-Control: no-store', FALSE );
|
|
|
|
$html_string = "<!DOCTYPE html><html><head><style>"
|
|
. "body {font-size:30px;background-color: black;"
|
|
. "color: #33cccc;text-align: center;width: 30em;"
|
|
. "margin-left: auto;margin-right: auto;}"
|
|
. "input[type=submit] {padding:5px 15px;"
|
|
. "font-size:25px;"
|
|
. "background-color: black;"
|
|
. "color: #33cccc;"
|
|
. "cursor:pointer;"
|
|
. "border: 1px solid #11bbcc;"
|
|
. "-webkit-border-radius: 5px;"
|
|
. "border-radius: 5px;}"
|
|
. "</style></head><body><br><br><br>"
|
|
. "<code>Entry portal: "
|
|
. "Please click the button to proceed.</code>"
|
|
. "<br><br><br><br><br><br><div class='form'>"
|
|
. "<form action='/ep' method='post'>"
|
|
. "<input type='hidden' name='portal' value='$request'>"
|
|
. "<input type='submit' value='Enter'><br>"
|
|
. "</form></div>"
|
|
. "<br><br><br><br><br><br><code>Sorry for this,"
|
|
. " it's just a lowlevel protection "
|
|
. "against scraping bots.</code></body></html>";
|
|
|
|
echo "$html_string";
|
|
|
|
quit($db, '');
|
|
}
|
|
}
|
|
|
|
// If enabled, inserts an invisible link, leading to the bot tarpit
|
|
function lay_trap($settings)
|
|
{
|
|
if ( ($settings['enable_bot_trap'] == TRUE) ) {
|
|
$triggers = array(
|
|
'tr', 'login', 'wellknown',
|
|
'wp-login', 'wp-json', 'wp',
|
|
'products', 'wp-users', 'wp-admin',
|
|
'wp-adminer', 'adminer', 'php-myadmin',
|
|
'wp-uploads', 'wp-content', 'wp-config',
|
|
'wp-includes', 'static', 'img',
|
|
'images', 'uploads', 'styles',
|
|
'style', 'server-info', 'private_key',
|
|
'server-status'
|
|
);
|
|
$count_triggers = count($triggers) - 1;
|
|
$fake_link = $triggers[rand(0, $count_triggers)];
|
|
echo "<div style=\"display:none\"><a href=/$fake_link></a></div>";
|
|
}
|
|
}
|
|
|
|
// checks if posts from bots can be received or not
|
|
function post_block_bot($db, $settings, $visitor_ip)
|
|
{
|
|
|
|
$current = time();
|
|
$max_age = $current - ($settings['max_post_timeframe'] * 60);
|
|
// the number from settings is in minutes, so times 60 for secs
|
|
|
|
if ( ($settings['max_post_global'] > 0) ) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type in ('bot', 'user')
|
|
AND event = 'post attempt'
|
|
AND unix_timestamp > '$max_age'");
|
|
|
|
$result = $statement->execute();
|
|
|
|
$counter = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$counter++;
|
|
}
|
|
|
|
if ( ($counter > $settings['max_post_global']) ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( ($settings['max_post_ip'] > 0) ) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type in ('bot', 'user')
|
|
AND event = 'post attempt'
|
|
AND ip = '$visitor_ip'
|
|
AND unix_timestamp > '$max_age'");
|
|
|
|
$result = $statement->execute();
|
|
|
|
$counter = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$counter++;
|
|
}
|
|
|
|
if ( ($counter > $settings['max_post_ip']) ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( ($settings['max_post_bot'] > 0) ) {
|
|
$statement = $db->prepare("SELECT unix_timestamp
|
|
FROM logs
|
|
WHERE type = 'bot'
|
|
AND event = 'post attempt'
|
|
AND unix_timestamp > '$max_age'");
|
|
|
|
$result = $statement->execute();
|
|
|
|
$counter = 0;
|
|
|
|
while ($row = $result->fetchArray(SQLITE3_NUM)) {
|
|
$counter++;
|
|
}
|
|
|
|
if ( ($counter > $settings['max_post_bot']) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// brings the user to the actual target that was requested before the
|
|
// portal took over
|
|
function redirect_target()
|
|
{
|
|
$target = $_POST['portal'];
|
|
|
|
header( "refresh:0;url=$target" );
|
|
|
|
$html_string = "<!DOCTYPE html><html><head><style>"
|
|
. "body {font-size:25px;"
|
|
. "background-color: black;"
|
|
. "color: #33cccc;"
|
|
. "text-align: center;"
|
|
. "width: 30em;"
|
|
. "margin-left: auto;"
|
|
. "margin-right: auto;}"
|
|
. "a:link, a:visited {color: red;}"
|
|
. "</style></head><body><br><br><br><code>"
|
|
. "Redirection ongoing. If that does not work, click"
|
|
. " <a href='$target'>here</a>.</code>";
|
|
|
|
echo "$html_string";
|
|
|
|
}
|
|
|
|
// Feed garbage links and texts to bots that follow invisible links.
|
|
// Feed even more garbage if the bot follows the garbage links.
|
|
// Feel free to add other variants in the arrays.
|
|
// There are nearly 10 billion possible links, and ca. 550 million
|
|
// possible text combinations. For some bots this is overdose.
|
|
function trap_me($db, $settings, $bot_ip)
|
|
{
|
|
|
|
$noun = array(
|
|
'Hermione', 'Gaius Cactus', 'The maniac',
|
|
'The orange menace', 'The fool on the hill', 'Captain Hook',
|
|
'Captain Futuro', 'Chaplain Miller', 'The ambassador of Fuggia',
|
|
'The space pope', 'An unremarkable stone', 'The three little piglets',
|
|
'The giant panda', 'Bickus Dickus', 'Incontenencia Buttocks',
|
|
'The phantom of the opera', 'Granny Smithi', 'Conani',
|
|
'Pippyn Longstockings', 'The ghost of Alberto Einsteino', 'The girl',
|
|
'The boy', 'Mr. Buourns', 'The turtle',
|
|
'Humpty-Trumpty', 'The elephant', 'The bear',
|
|
'The pope', 'Oxymandias', 'The pied piper',
|
|
'Sandor Bollocks', 'Sir Poosalot', 'The man',
|
|
'The octopus', 'Wondery Woman', 'The woman',
|
|
'Supiman', 'Spidyman', 'Bylbo Bagman',
|
|
'The eggman', 'The walrus', 'Battyman',
|
|
'Dumbledutt', 'Gullom', 'The cyberfuck',
|
|
'The lion', 'The lion king', 'An oldtimer from Tennesse',
|
|
'The alligator', 'Micky Moose', 'Marlon Brandoff',
|
|
'Suedwester Stallone', 'A bag full of hot air', 'A murder of crows',
|
|
'A litter of kittens', 'Some teeny-tiny gooslings', 'Donald Duckling',
|
|
'Wallaby', 'All the kings man', 'The rhino',
|
|
'The dingo'
|
|
);
|
|
$count_noun = count($noun) - 1;
|
|
|
|
$verb = array(
|
|
'deducted', 'wondered', 'sat on the wall',
|
|
'made a big fall', 'devoured eight boy scouts', 'played chess',
|
|
'kissed me in the dark', 'played football', 'played the flute',
|
|
'played the violin', 'self-abused', 'smoked some crack',
|
|
'breakdanced', 'icedanced', 'sneezed',
|
|
'lost their cool', 'got engaged', 'got clipped',
|
|
'jumped', 'dozed off', 'ran away',
|
|
'spit flames', 'got tarred and feathered','consumed several boars',
|
|
'drank the blood of six sheep', 'engaged in all-open unarmed combat',
|
|
'managed', 'mounted an icebear',
|
|
'brought life into the world', 'grinned',
|
|
'ran', 'machine-gunned some sandbags', 'made her voice heard',
|
|
'did some weed', 'walked', 'crawled',
|
|
'fought', 'was gung-ho', 'farted',
|
|
'bullwhipped', 'ate some icecream', 'let one fly',
|
|
'danced', 'sharpened their teeth',
|
|
'moved to the sound of music', 'waited', 'burped',
|
|
'manhandled Cesaro Romao', 'inhaled some DNA altering fumes',
|
|
'knocked out the oppressor', 'burst in tears', 'imitated Ronald Regan',
|
|
'goggled'
|
|
);
|
|
$count_verb = count($verb) - 1;
|
|
|
|
$adverb = array(
|
|
'fast', 'slowly', 'well', 'manly', 'badly',
|
|
'angrily', 'loudly', 'lewldy', 'in a flexible way',
|
|
'ignoring the grammar', 'with utter disrespect',
|
|
'quietly', 'in the way of the old days',
|
|
'gently, but firmly', 'very abruptly', 'in a textbook fashion',
|
|
'in a heated atmosphere', 'very concentrated',
|
|
'ok', 'with the speed of light cigarettes',
|
|
'during the better part of the day','nervously, as if under pressure',
|
|
'dreamily', 'with the elegance of a manatee',
|
|
'with the grace of a crap eating fly','with the speed of a slow bird',
|
|
'with a lot of mediocraty', 'ignoring the danger like a true hero',
|
|
'seeking distraction', 'like they do in the movies',
|
|
'fast, compared to an ant,', 'slow, almost mechanical',
|
|
'as if gravity was void', 'as if it was fate',
|
|
'in days of yore', 'from dusk till dawn',
|
|
'in the middle of the day', 'during quiet hours',
|
|
'before the break of dawn', 'momentarily',
|
|
'like crazy', 'like fuck'
|
|
);
|
|
$count_adverb = count($adverb) - 1;
|
|
|
|
$finish = array(
|
|
'on the emerald isle.', 'in space.', 'in the woods',
|
|
'on the bottom of the ocean.', 'in the Kalahari',
|
|
'in Siam', 'on a Tetris board.',
|
|
'where the sun don\'t shine.', 'in Oklahoma.',
|
|
'in Brazil.', 'by the sea',
|
|
'in the Cristall Palace','near the pigsty',
|
|
'close to the magnetic north pole.',
|
|
'closer than you might think.', 'in New York.',
|
|
'on the internet.', 'on mars.', 'more to the right.',
|
|
'on the Canaries', 'in Askuban.', 'to the cellar.',
|
|
'in the english garden.', 'on the sea.', 'in the living room.',
|
|
'down by the docks.', 'on twitter, now shit.',
|
|
'on the tennis court.', 'in the ceiling.', 'in the street.',
|
|
'in the streets of London.', 'in the presence of his noodleness.',
|
|
'for the fame of Eris.', 'in an alley.',
|
|
'during a replubican convention.', 'on the roof.',
|
|
'in my neighbors garden.', 'on the plane.', 'in the car.',
|
|
'on the train.', 'in the forest.'
|
|
);
|
|
$count_finish = count($finish) - 1;
|
|
|
|
$reply = array(
|
|
'What can you do ?', 'How is this possible ?',
|
|
'And it\'s all your fault.', 'And it\'s all my fault.',
|
|
'Who will be paying for that ?',
|
|
'And who is to blame, that\'s what I want to know.',
|
|
'And the blame is on us all.', 'I need some booze now.',
|
|
'I need a smoke.', 'I pity the fool who finds this funny !',
|
|
'These are the times we live in.','And what is wrong with that ?',
|
|
'How do you do ?', 'God shave the queen.',
|
|
'For fucks sake, not again',
|
|
'And that\'s exactly why we need a union.',
|
|
'Read it in the scriptures, if you don\'t believe me.',
|
|
'And this was not the first time.',
|
|
'Happens more often than you\'d think.',
|
|
'Why ? Just why ?', 'Technology will solve it all.',
|
|
'Progress will resolve it all.', 'The prophet saw this coming.',
|
|
'Many have tried, Many have tried and failed....',
|
|
'I say blimey.', 'I have said it before, we need more weed.',
|
|
'Clearly, we need more surveillance.',
|
|
'Nuke it from space, I say.',
|
|
'There are not enough catholics in this world.',
|
|
'Can you imagine ?', 'Well, I would never !',
|
|
'I had never seen such a thing !',
|
|
'Shocked, I watched the events unfold.',
|
|
'I could not believe my eyes.',
|
|
'So anyway, I says to Mabel, Mabel, I says...',
|
|
'What would Jebus do ?', 'Here\'s Tom with the weather.',
|
|
'Buy more bullets.', 'And that is not ok.',
|
|
'Finally.', 'Airstrike, now.',
|
|
'More after the commercial.', 'Back to you, Morbot.',
|
|
'Do I have no rights at all ?', 'What is the world coming to ?',
|
|
'To shreds, you say ?', 'And that made me feel very sad.',
|
|
'And that made me feel very horny.',
|
|
'Too beaucoup, too ... beaucoup.', 'Can you dig it ?',
|
|
'Feel me ?',
|
|
'Will you be able to explain this ?',
|
|
'My neighbor foretold it. He\'s good at that.',
|
|
'One more beer could not hurt, I thought.',
|
|
'"At this time of year ?" I thought to myself.',
|
|
'Buy more toilet paper.', 'We need more rocks.',
|
|
'Get them young, I say.',
|
|
'And if that\'s not good enough for you, I don\'t know what is',
|
|
'Polar bears are mens best friends.', 'Kitties are cuddly.',
|
|
'My dog can fart really loud.',
|
|
'And we will never hear the end of it.', 'Really ?',
|
|
'And I blame todays society.'
|
|
);
|
|
$count_reply = count($reply) - 1;
|
|
|
|
$triggers = array(
|
|
'tr', 'login', 'wellknown',
|
|
'wp-login', 'wp-json', 'wp',
|
|
'products', 'wp-users', 'wp-admin',
|
|
'wp-adminer', 'adminer', 'php-myadmin',
|
|
'wp-uploads', 'wp-content', 'wp-config',
|
|
'wp-includes', 'static', 'img',
|
|
'images', 'uploads', 'styles',
|
|
'style', 'server-info', 'private_key',
|
|
'server-status'
|
|
);
|
|
$count_triggers = count($triggers) - 1;
|
|
|
|
$link = read_pretty_vars("last", 'number', 1);
|
|
// we take the first digit of the link
|
|
// to check if this is a first time visitor
|
|
|
|
if ($link > 0) {
|
|
// if the bot followed a link, feed more garbage
|
|
$fake_loops = rand(500, 1000);
|
|
// 500 ... 1000 garbage links should do it
|
|
$log_message = "Level 2";
|
|
log_event($db, $settings, 'bot', $log_message, $bot_ip);
|
|
} else {
|
|
$fake_loops = rand(10, 20);
|
|
// just send 10...20 garbage links
|
|
// to first time visitors
|
|
$log_message = "Level 1";
|
|
log_event($db, $settings, 'bot', $log_message, $bot_ip);
|
|
}
|
|
|
|
$html_string = '<title> bot tarpit </title>'
|
|
. '<h1>in case you are a normal visitor, please note that '
|
|
. 'this page has no actual content,'
|
|
. ' but is just build to annoy crawling '
|
|
. 'bots that disrespect robots.txt</h1>';
|
|
|
|
if ( ($settings['enable_bot_block'] == TRUE) ) {
|
|
$html_string .= '<h1>Don\'t follow the links,'
|
|
. ' and don\'t visit this page again,'
|
|
. ' or you might get blocked.</h1>';
|
|
}
|
|
|
|
for ($fake=0; $fake<$fake_loops; $fake++) {
|
|
$line = $noun[rand(0, $count_noun)] . ' ' .
|
|
$verb[rand(0, $count_verb)] . ' ' .
|
|
$adverb[rand(0, $count_adverb)] . ' ' .
|
|
$finish[rand(0, $count_finish)] . ' ' .
|
|
$reply[rand(0, $count_reply)];
|
|
$fake_link = $triggers[rand(0, $count_triggers)];
|
|
$post_text = "<a href=/$fake_link/" . rand() . ">$line</a></div>";
|
|
$html_string .= "<br><br>$post_text<br><br>";
|
|
}
|
|
|
|
$html_string .= '</html>';
|
|
|
|
echo "$html_string";
|
|
}
|
|
|
|
// EOF
|