Djangoに偽の管理サイトを用意するdjango-admin-honeypot

django-admin-honeypotを試してみました。
django-admin-honeypot/admin_honeypot at develop · dmpayton/django-admin-honeypot · GitHub


ハニーポットとは

ハニーポット (英語: Honeypot) は、コンピュータセキュリティ用語としては、不正アクセスを受けることに価値を持つシステムのことを指す。元来は「蜜(の詰まった)壷」の意味で、何らかの有益そうな情報や資源がありそうな場所を用意して、それにつられた者を観察したり、肝心な部分で被害を出さないために目を逸らせたり、コンピュータ・フォレンジックスを行うための証拠を集めたりする、一種の囮手法に使われる。手法そのものをハニーポットと呼ぶこともある。
ハニーポット - Wikipedia

django-admin-honeypotは偽のadminを提供して、そこへのアクセスを記録してくれます。


pip installして

pip install django-admin-honeypot


INSTALLED_APPSに追加

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'admin_honeypot'
)


syncdbすると、admin_honeypot_loginattemptテーブルが作成されます。

Creating tables ...
Creating table admin_honeypot_loginattempt
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)


urls.pyにルーティングの定義を追加します。
本物のadminはadminとは別のurlを定義しておきます。

urlpatterns = patterns(''
    ...
    url(r'^admin/', include('admin_honeypot.urls')),
    url(r'^secret/', include(admin.site.urls)),
)

起動して/admin/にアクセスしてみます。

普通の管理サイトに見えますね。でも存在するsuperuserでもログインはできません。


/secret/に用意した本物の管理サイトにログインすると、先ほどの偽管理サイトのログイン失敗が記録されてます。


なかなかおもしろい


ソースをみてみる

絶対に失敗するログインフォームw

class HoneypotLoginForm(AdminAuthenticationForm):
    def clean(self):
        ## Always raise the default error message, because we don't
        ## care what they entered here.
        raise forms.ValidationError(ERROR_MESSAGE)

あとsettings.pyでADMIN_HONEYPOT_EMAIL_ADMINSをTrueに設定すると、メールを飛ばせるようになっている。

from admin_honeypot.signals import honeypot
from django.conf import settings
from django.contrib.sites.models import get_current_site
from django.core.mail import mail_admins
from django.core.urlresolvers import reverse
from django.template.loader import render_to_string


def notify_admins(instance, request, **kwargs):
    site = get_current_site(request)
    path = reverse('admin:admin_honeypot_loginattempt_change', args=(instance.pk,))
    admin_detail_url = 'http://{0}{1}'.format(site.domain, path)
    context = {
        'request': request,
        'instance': instance,
        'site': site,
        'admin_detail_url': admin_detail_url,
    }
    subject = render_to_string('admin_honeypot/email_subject.txt', context).strip()
    message = render_to_string('admin_honeypot/email_message.txt', context).strip()
    mail_admins(subject=subject, message=message)

if getattr(settings, 'ADMIN_HONEYPOT_EMAIL_ADMINS', True):
    honeypot.connect(notify_admins)


面白いけど、ブルートフォースアタックみたいなのされたら、データが大量にinsertされるし、メールもたくさん飛んでくるんだな、これ