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

Zablokowane wysyłanie poczty na Gmaila

Od około tygodnia czasu zacząłem dostawać zwrotki z @gmaila:

<[email protected]>: host gmail-smtp-in.l.google.com[2a00:1450:400c:c08::1b]
    said: 550-5.7.1 [2a01:7e00::f03c:91ff:fedb:7cbc      19] Our system has
    detected that 550-5.7.1 this message is likely suspicious due to the very
    low reputation of 550-5.7.1 the sending domain. To best protect our users
    from spam, the message 550-5.7.1 has been blocked. Please visit 550 5.7.1
    https://support.google.com/mail/answer/188131 for more information.
    s11si27746295wrv.40 - gsmtp (in reply to end of DATA command)

Zastanawiałem się co mogło być przyczyną, sprawdzenie domeny i adresu IP czy znajduje się na jakichś czarnych listach nie dało żadnych rezultatów.

http://www.anti-abuse.org/multi-rbl-check-results/

Rejestracja domeny pocztowej w https://postmaster.google.com (wcześniej nawet nie wiedziałem, że coś takiego jest) wykazała, że jakieś maile były zgłaszane jako spam, bez jakichkolwiek szczegółów, jedynie daty.

Zacząłem grzebać w logach serwera i co się okazało? Tona ruskich adresów @mail.ru w logach serwera SMTP postfix ze statusem wysłane, ale zablokowane przez serwer odbiorcy (mimo, że serwer pocztowy nie zezwala na wysyłanie nieautoryzowanym użytkownikom). Skąd?

Jun 26 21:27:13 server postfix/smtp[20474]: 4E64DE74167: to=<[email protected]>, relay=mxs.mail.ru[94.100.180.104]:25, delay=13076, delays=13006/69/0.72/0.23, dsn=4.0.0, status=deferred (host mxs.mail.ru[94.100.180.104]

Znalezienie źródła, kto rozpoczął wysyłanie, wymaga wyszukania identyfikatora, w tym wypadku 4E64DE74167 w poprzednio zalogowanych informacjach. I co się okazało? Że wysyła je lokalne konto użytkownika na serwerze, prawdopodobnie przez aplikację PHP…

Okazało się, że na jednym z nieużywanych for postawionych na Invision Power Board – boty tworzyły spamerskie wiadomości – nic nowego, ale boty wiedziały, że forum oferuje opcję wysłania wskazanej wiadomości na wybrany adres email i masowo spamowały nimi tysiące maili…

Nauczka na przyszłość – jak widać spam na forach nie służy jedynie do uprzykrzania życia użytkownikom forum, ale również do masowego spamowania. Teraz już wiem 😉

PS. A tutaj można napisać apelację do Google https://support.google.com/mail/troubleshooter/2696779 jakby ktoś miał podobny problem.

PS2. Mały update – warto wyczyścić kolejkę wiadomości postfixa, bo się okazało, że mi ponad 5000 maili spamerskich wisiało w kolejce i cały czas były próby ich dostarczenia… ehh 😉

PS3. Po około 2 dniach od wykrycia problemu, zgłoszeniu do Google problem został rozwiązany (sam jestem zaskoczony, że tak szybko).

PS4. Problem nie został rozwiązany, tak tylko wyglądało i z tego co czytam obecnie po forach gmaila wielu ludzi ma ten sam problem. Domena dostaje niską ocenę i nie sposób dotrzeć do supportu Gmaila w celu naprawy problemu… Pojedyncze wiadomości do skrzynek Gmaila wysyłam z dedykowanej skrzynki @gmail, a masowe wiadomości dla klientów z domeny .net na innym adresie IP. Jak widać prosta z pozoru rzecz potrafi napsuć krwi.

https://support.google.com/mail/thread/10570288?hl=en