BOT対策

諏訪子 <suwako@076.moe>、2025-12-12 19:40
コミット 47cf4f9f5467c94a01b041cdd71f30007150ae18 ・親 6d6fa82 ・ファイルを見る

4個のファイル、+84 -7

@@ -20,6 +20,7 @@
2020
2121 $doLogin = $_SERVER['REQUEST_METHOD'] === 'POST';
2222 $error = '';
23+ $nyuU = '';
2324
2425 if ($doLogin) {
2526 if (!\verify_csrf_token($_POST['csrf_token'])) {
@@ -29,13 +30,21 @@
2930 unset($_POST['csrf_token']);
3031
3132 $a = [];
32- if (count($_POST) === 2) {
33+ $isBot = false;
34+ if (count($_POST) === 4) {
3335 $i = 0;
3436 foreach ($_POST as $p) {
3537 $a[(int)$i] = $p;
38+ if ($i >= 2 && $p != '') $isBot = true;
3639 $i++;
3740 }
3841 }
42+
43+ if ($isBot) {
44+ header('Location: /');
45+ exit();
46+ }
47+
3948 $auth = new Auth($a[0]);
4049 $res = $auth->isUserExist($a[0]);
4150 if (!$res->isSuccess) {
@@ -43,6 +52,7 @@
4352 } else {
4453 $result = $auth->setToken($a[0], $a[1]);
4554 if (!$result->isSuccess) {
55+ $nyuU = $a[0];
4656 $error = $result->message;
4757 } else {
4858 header('Location: /');
@@ -60,6 +70,7 @@
6070 $tmpl->assign('menu', $this->getMenu());
6171 $tmpl->assign('description', $description);
6272 $tmpl->assign('error', $error);
73+ $tmpl->assign('nyuU', $nyuU);
6374
6475 $tmpl->render('login');
6576 } catch (\Exception $e) {
@@ -108,12 +119,19 @@
108119 unset($_POST['csrf_token']);
109120
110121 $a = [];
111- if (count($_POST) === 4) {
122+ $isBot = false;
123+ if (count($_POST) === 8) {
112124 $i = 0;
113125 foreach ($_POST as $p) {
114126 $a[(int)$i] = $p;
127+ if ($i >= 4 && $p != '') $isBot = true;
115128 $i++;
116129 }
130+ }
131+
132+ if ($isBot) {
133+ header('Location: /');
134+ exit();
117135 }
118136
119137 $auth = new Auth;
変更 util.php
@@ -44,6 +44,46 @@
4444 die();
4545 }
4646
47+function ffs(): void {
48+ echo '<style>html { color: #fcfcfc; background-color: #232023; } body { margin: 0; }</style>';
49+ echo '<header style="padding: 10px 0; display: flex; justify-content: space-evenly; background-color: #b61729; margin-bottom: 20px; position: sticky; top: 0;"><div><b>F</b>OR</div> <div><b>F</b>UCKS</div> <div><b>S</b>AKE</div></header>';
50+
51+ $stack = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 50);
52+ $st = [];
53+ unset($stack[0]);
54+ $i = 0;
55+
56+ echo '<pre>';
57+ print_r($stack);
58+ echo '<pre>';
59+ foreach ($stack as $s) {
60+ if (isset($s['file'])) $st[$i]['file'] = $s['file'].(isset($s['line']) ? ':'.$s['line'] : '');
61+ else $st[$i]['file'] = '';
62+ if (isset($s['function'])) $st[$i]['func'] = (isset($s['class']) ? $s['class'].(isset($s['type']) ? $s['type'] : '::') : '').$s['function'];
63+ else $st[$i]['func'] = '';
64+ if (isset($s['object'])) $st[$i]['objs'] = $s['object'];
65+ else $st[$i]['objs'] = new \stdClass;
66+ if (isset($s['args'])) $st[$i]['args'] = $s['args'];
67+ else $st[$i]['args'] = [];
68+ $i++;
69+ }
70+ unset($stack[$i]);
71+
72+ foreach ($st as $s) {
73+ echo '<div>';
74+ echo '<b>ファイル:</b>';
75+ echo $s['file'].'<br />';
76+ echo '<b>関数:</b>';
77+ echo $s['func'].'<br />';
78+ echo '<b>オブジェクト:</b>';
79+ echo print_r($s['objs']).'<br />';
80+ echo '<b>その他:</b>';
81+ echo print_r($s['args']).'<br />';
82+ echo '</div>';
83+ }
84+ die();
85+}
86+
4787 function base58btc_encode(string $bin): string {
4888 $a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
4989 $base = 58;
@@ -113,8 +153,7 @@
113153 }
114154
115155 function randstr(): string {
116- srand((int)floor(time() / (60*60*24)));
117- $len = rand(1, 20);
156+ $len = random_int(1, 20);
118157 return bin2hex(random_bytes($len));
119158 }
120159
@@ -178,7 +217,7 @@
178217 }
179218
180219 function verify_csrf_token(string $token): bool {
181- return hash_equals(getcookie('csrf_token'), $token);
220+ return null !== getcookie('csrf_token') && hash_equals(getcookie('csrf_token'), $token);
182221 }
183222 }
184223
@@ -16,19 +16,27 @@
1616 <form action="/login" method="POST">
1717 {$ $username = randstr() $}
1818 {$ $password = randstr() $}
19+ {$ $botUsername = randstr() $}
20+ {$ $botPassword = randstr() $}
1921 <table>
2022 <tbody>
2123 <tr>
2224 <td><label for="{{ $username }}">ユーザー名:</label></td>
23- <td><input type="text" id="{{ $username }}" name="{{ $username }}" /></td>
25+ <td><input type="text" id="{{ $username }}" name="{{ $username }}" value="{{ $nyuU }}" /></td>
2426 </tr>
2527 <tr>
2628 <td><label for="{{ $password }}">パスワード:</label></td>
27- <td><input type="password" id="{{ $password }}" name="{{ $password }}" /></td>
29+ <td><input type="password" id="{{ $password }}" name="{{ $password }}" value="" /></td>
2830 </tr>
2931 <tr>
3032 <td></td>
3133 <td>
34+ <div style="position:absolute; left:-9999px;">
35+ <input type="text" id="{{ $username }}" name="{{ $botUsername }} value="" />
36+ <input type="password" id="{{ $password }}" name="{{ $botPassword }}" value="" />
37+ </div>
38+
39+ <a href="/?bot=1" style="display:none"></a>
3240 <input type="hidden" id="csrf_token" name="csrf_token" value="{{ make_csrf_token() }}" />
3341 <button>サインイン</button>
3442 </td>
@@ -18,6 +18,10 @@
1818 {$ $password = randstr() $}
1919 {$ $passwordVerify = randstr() $}
2020 {$ $email = randstr() $}
21+ {$ $botUsername = randstr() $}
22+ {$ $botPassword = randstr() $}
23+ {$ $botPasswordVerify = randstr() $}
24+ {$ $botEmail = randstr() $}
2125 <table>
2226 <tbody>
2327 <tr>
@@ -39,6 +43,14 @@
3943 <tr>
4044 <td></td>
4145 <td>
46+ <div style="position:absolute; left:-9999px;">
47+ <input type="text" id="{{ $botUsername }}" name="{{ $botUsername }} value="" />
48+ <input type="password" id="{{ $botPassword }}" name="{{ $botPassword }}" value="" />
49+ <input type="password" id="{{ $botPasswordVerify }}" name="{{ $botPasswordVerify }}" />
50+ <input type="email" id="{{ $botEmail }}" name="{{ $botEmail }}" value="" />
51+ </div>
52+
53+ <a href="/?bot=1" style="display:none"></a>
4254 <input type="hidden" id="csrf_token" name="csrf_token" value="{{ make_csrf_token() }}" />
4355 <button>登録</button>
4456 </td>