Anti-Spam Form dla Yii2 Framework

Anti-Spam Form jest komponentem zastępującym standardowe formy ActiveForm dla Yii2 Framework z ochroną anty-spamową, które są niewidoczne w kodzie HTML dla botów spamowych i narzędzi do zbierania danych (tzw. harvestery).

Jaka jest idea stojąca za formularzami antyspamowymi?

Koncepcja jest prosta. Boty spamowe w większości przypadków są prostymi narzędziami. Potrafią czytać Twoją stronę, szukać znaczników <form> w kodzie HTML i sztucznie wypełniać pola formularza i wysyłać go.

Zwykły bot spamowy to w 99% przypadków web scraper napisany w Pythonie pobierający zawartość strony HTML bez wykonywania kodu JS.

Ale jedną rzeczą pominiętą w metodach wykrywania spamu jest to, że boty spamowe zwykle nie mogą przetwarzać kodu JavaScript. Jest to czasochłonne i wymaga interpretera JS do wykonania kodu na stronie. Aby to osiągnąć należy już wykorzystać bardziej złożone i wolniejsze silniki, zwykle oparte o Chromium.

Jak pokonać spam boty?

Proste – umieścić formularze HTML z zakodowanymi tagami HTML <form> w formie kodu JavaScript. Nie cały formularz, ale początkowy tag ze wszystkimi jego właściwościami.

Nagle boty spamowe nie są w stanie go znaleźć. Mniej spamu bez zbyt wiele pracy.

Zwykle kod formularza wygląda następująco:

<div class="active-form">
  <!--visible <form> tag -->  
  <form id="contact-form" action="/contact" method="post">
    <input type="hidden" name="_csrf" value="u18o4NxJC5lZEhHhjpMTd-c7p3ZzYzl0wvsXMiefJJ_0HWGpr1pm6x5Qa4vnpVw5o1yXNzEQ7USUlE9HVNlGzQ==">
    <div class="form-group field-contactform-name required">
      <label class="control-label" for="contactform-name">Name</label>
      <input type="text" id="contactform-name" class="form-control" name="ContactForm[name]" aria-required="true">
      <p class="help-block help-block-error"></p>
    </div>
    <div class="form-group field-contactform-email required">
      <label class="control-label" for="contactform-email">Email</label>
      <input type="email" id="contactform-email" class="form-control" name="ContactForm[email]" aria-required="true">
      <p class="help-block help-block-error"></p>
    </div>
    <div class="form-group field-contactform-subject required">
      <label class="control-label" for="contactform-subject">Subject</label>
      <input type="text" id="contactform-subject" class="form-control" name="ContactForm[subject]" aria-required="true">
      <p class="help-block help-block-error"></p>
    </div>
    <div class="form-group field-contactform-body required">
      <label class="control-label" for="contactform-body">Body</label>
      <textarea id="contactform-body" class="form-control" name="ContactForm[body]" rows="6" aria-required="true"></textarea>
      <p class="help-block help-block-error"></p>
    </div>
    <div class="form-group field-contactform-verifycode">
      <label class="control-label" for="contactform-verifycode">Verification Code</label>
      <div class="row">
        <div class="col-xs-4 col-sm-3 col-md-3">
          <img id="contactform-verifycode-image" src="/site/captcha?v=62cff29d6ebe55.89254929" alt="">
        </div>
        <div class="col-xs-2 col-sm-3 col-md-3">
          <input type="text" id="contactform-verifycode" class="form-control" name="ContactForm[verifyCode]">
        </div>
        <div class="col-xs-6 col-sm-6 col-md-6">
          <button type="submit" class="btn btn-block btn-primary" name="contact-button">Send</button>
        </div>
      </div>
      <p class="help-block help-block-error"></p>
    </div>
  </form>
</div>

Po wykorzystaniu komponentu anty-spamerskiego:

<div class="active-form">
  <!-- <form> tag dynamically generated with the JavaScript code -->    
  <script>
    document.write(atob("PGZvcm0gaWQ9ImNvbnRhY3QtZm9ybSIgYWN0aW9uPSIvY29udGFjdCIgbWV0aG9kPSJwb3N0Ij4KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0iX2NzcmYiIHZhbHVlPSJ1MFczN0JLaDJOQko2Q2lVeTFxc3R3OEp6aC1mcUxxOXRnOEpQem9CUjZfMEJfNmxYX0sxb2c2cVV2NmliT1A1UzI3LVh0M2F6bzNnWUZGS1NVY2xfUT09Ij4="));
  </script>
  <div class="form-group field-contactform-name required">
    <label class="control-label" for="contactform-name">Name</label>
    <input type="text" id="contactform-name" class="form-control" name="ContactForm[name]" aria-required="true">
    <p class="help-block help-block-error"></p>
  </div>
  <div class="form-group field-contactform-email required">
    <label class="control-label" for="contactform-email">Email</label>
    <input type="email" id="contactform-email" class="form-control" name="ContactForm[email]" aria-required="true">
    <p class="help-block help-block-error"></p>
  </div>
  <div class="form-group field-contactform-subject required">
    <label class="control-label" for="contactform-subject">Subject</label>
    <input type="text" id="contactform-subject" class="form-control" name="ContactForm[subject]" aria-required="true">
    <p class="help-block help-block-error"></p>
  </div>
  <div class="form-group field-contactform-body required">
    <label class="control-label" for="contactform-body">Body</label>
    <textarea id="contactform-body" class="form-control" name="ContactForm[body]" rows="6" aria-required="true"></textarea>
    <p class="help-block help-block-error"></p>
  </div>
  <div class="form-group field-contactform-verifycode">
    <label class="control-label" for="contactform-verifycode">Verification Code</label>
    <div class="row">
      <div class="col-xs-4 col-sm-3 col-md-3">
        <img id="contactform-verifycode-image" src="/site/captcha?v=62cff214a00af2.73036299" alt="">
      </div>
      <div class="col-xs-2 col-sm-3 col-md-3">
        <input type="text" id="contactform-verifycode" class="form-control" name="ContactForm[verifyCode]">
      </div>
      <div class="col-xs-6 col-sm-6 col-md-6">
        <button type="submit" class="btn btn-block btn-primary" name="contact-button">Send</button>
      </div>
    </div>
    <p class="help-block help-block-error"></p>
  </div>
  </form>
</div>

Kody źródłowe https://github.com/PELock/yii2-anti-spam-form

Paczka dla PHP https://packagist.org/packages/pelock/yii2-anti-spam-form

Szyfrowanie w Ruby

Usługa StringEncrypt została wzbogacona o szyfrowanie i generowanie kodu w języku programowania Ruby.

Szyfrowanie StringEncrypt

StringEncrypt pozwala na szybkie i sprawne zaszyfrowanie dowolnych stringów, każdorazowo generując inny algorytm szyfrujący dane, a na wyjściu zwraca kod deszyfrujący w wybranym języku programowania.

Dla czytelników Security News darmowy kod aktywacyjny, pozwalający skorzystać ze wszystkich dostępnych opcji szyfrujących:

CEB4-A1A7-797C-F65F

Filtr na trolla

Bycie trollem internetowym ma swoje plusy i minusy, można kogoś zbluzgać bez powodu i cieszyć się swoją głupotą, czasami jednak administratorzy stron walczą z trollami stosując wymyślne filtry.

Tak jest lub było w przypadku wykrywania znanego „klaczowego” trolla okupującego swego czasu forum 4programmers, sprytny administrator Adam Boduch postanowił walczyć z twórczością trolla stosując taki oto wymyślny filtr:

<?php

/* ... */

Wrapper\Engine::instance()->atInit(function($engine) {
    $is_troll_z_play = has_troll_cookie();

    if ($_SERVER['REQUEST_METHOD'] === 'POST' && @$_GET['mode'] === 'submit') {
        if (isset($_POST['username']) && isset($_POST['content'])) { // tylko anonimow
            $matches_nick = troll_count_matches($_POST['username'], array(
                '/deus/i'               => 2.0,
                '/klacz/i'              => 2.0,
                '/demonical.?monk/i'    => 2.0
            ));
            $pattern_body = array(
                '/(?<!u)rucha/i'        => 1.0,
                '/klacz/i'              => 1.0,
                '/kutas/i'              => 1.0,
                '/sra/i'                => 1.0,
                '/g(ó|o)wn/i'          => 1.0,
                '/sperm/i'              => 1.0,
                '/ss(a|ie)/i'           => 0.5,
                '/wyli(z|ż)/i'         => 0.5,
                '/stajni/i'             => 0.5,
                '/zoofil/i'             => 0.5
            );
            $matches_body = troll_count_matches($_POST['content'], $pattern_body);

            if (isset($_POST['subject'])) { // nowy temat
                $matches_body += 1.5 * troll_count_matches($_POST['subject'], $pattern_body);
                $matches_body += 1.5 * troll_count_matches($_POST['tag'], $pattern_body);
            }
            if ($matches_nick + $matches_body > 2 || has_troll_cookie()) {
                $is_troll_z_play = true;

                $engine->log('contents.log', array(
                    'username'  => $_POST['username'],
                    'content'   => $_POST['content'],
                    'title'     => @$_POST['title'],
                    'tag'       => @$_POST['tag']
                ));
            }
        }
    }
    if ($is_troll_z_play) {
        define('TROLL_Z_PLAY', true);

        unset($_COOKIE['sid']);
        unset($_COOKIE['temp']);
    }
});

/* ... */

Regularne wyrażenia w połączeniu z systemem punktacji pozwoliły raz na zawsze pozbyć się trolla z forum, a Wam prezentuję to jako znakomity pomysł na wykrywanie tego typu niechcianych treści na stronach.

Jak oddać głos w PHP

Prosty skrypt, który zrobiłem dla znajomego, pozwalający automatycznie oddać głos w ankiecie (może to nie za bardzo etyczne, ale kogo to obchodzi).

Przykładowa forma głosowania (update, dzięki Tomek) wygląda tak:



Forma zawiera 3 ukryte pola (może to być np. identyfikator głosowania) oraz button Submit, należy również zwrócić uwagę na sposób przesyłania danych, tzn. POST lub GET. Skrypt do głosowania:

 urlencode('param 1 value'),
                'param2' => urlencode('param 2 value'),
                'param3' => urlencode('param 3 value'),
                'submit' => urlencode('Submit vote')
        );

// zbuduj poprawny ciag dla cURL
foreach($fields as $key => $value)
{
        $fields_string .= $key.'='.$value.'&';
}

rtrim($fields_string, '&');

$ch = curl_init();

// adres strony
curl_setopt($ch, CURLOPT_URL, $url);

// ilosc parametrow
curl_setopt($ch, CURLOPT_POST, count($fields));

// parametry POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);

// przegladarka
curl_setopt($ch, CURLOPT_USERAGENT, array_rand($agents));

// zwroc tylko wynik
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);

curl_close($ch);

// wyswietl wynikowy kod html
//echo $result;

?>

Skrypt wymaga zainstalowanej biblioteki cURL.