BOT対策
諏訪子 <suwako@076.moe>、2025-12-12 19:40
コミット 47cf4f9f5467c94a01b041cdd71f30007150ae18
・親 6d6fa82
・ファイルを見る
4個のファイル、+84 -7
| @@ -20,6 +20,7 @@ | ||
| 20 | 20 | |
| 21 | 21 | $doLogin = $_SERVER['REQUEST_METHOD'] === 'POST'; |
| 22 | 22 | $error = ''; |
| 23 | + $nyuU = ''; | |
| 23 | 24 | |
| 24 | 25 | if ($doLogin) { |
| 25 | 26 | if (!\verify_csrf_token($_POST['csrf_token'])) { |
| @@ -29,13 +30,21 @@ | ||
| 29 | 30 | unset($_POST['csrf_token']); |
| 30 | 31 | |
| 31 | 32 | $a = []; |
| 32 | - if (count($_POST) === 2) { | |
| 33 | + $isBot = false; | |
| 34 | + if (count($_POST) === 4) { | |
| 33 | 35 | $i = 0; |
| 34 | 36 | foreach ($_POST as $p) { |
| 35 | 37 | $a[(int)$i] = $p; |
| 38 | + if ($i >= 2 && $p != '') $isBot = true; | |
| 36 | 39 | $i++; |
| 37 | 40 | } |
| 38 | 41 | } |
| 42 | + | |
| 43 | + if ($isBot) { | |
| 44 | + header('Location: /'); | |
| 45 | + exit(); | |
| 46 | + } | |
| 47 | + | |
| 39 | 48 | $auth = new Auth($a[0]); |
| 40 | 49 | $res = $auth->isUserExist($a[0]); |
| 41 | 50 | if (!$res->isSuccess) { |
| @@ -43,6 +52,7 @@ | ||
| 43 | 52 | } else { |
| 44 | 53 | $result = $auth->setToken($a[0], $a[1]); |
| 45 | 54 | if (!$result->isSuccess) { |
| 55 | + $nyuU = $a[0]; | |
| 46 | 56 | $error = $result->message; |
| 47 | 57 | } else { |
| 48 | 58 | header('Location: /'); |
| @@ -60,6 +70,7 @@ | ||
| 60 | 70 | $tmpl->assign('menu', $this->getMenu()); |
| 61 | 71 | $tmpl->assign('description', $description); |
| 62 | 72 | $tmpl->assign('error', $error); |
| 73 | + $tmpl->assign('nyuU', $nyuU); | |
| 63 | 74 | |
| 64 | 75 | $tmpl->render('login'); |
| 65 | 76 | } catch (\Exception $e) { |
| @@ -108,12 +119,19 @@ | ||
| 108 | 119 | unset($_POST['csrf_token']); |
| 109 | 120 | |
| 110 | 121 | $a = []; |
| 111 | - if (count($_POST) === 4) { | |
| 122 | + $isBot = false; | |
| 123 | + if (count($_POST) === 8) { | |
| 112 | 124 | $i = 0; |
| 113 | 125 | foreach ($_POST as $p) { |
| 114 | 126 | $a[(int)$i] = $p; |
| 127 | + if ($i >= 4 && $p != '') $isBot = true; | |
| 115 | 128 | $i++; |
| 116 | 129 | } |
| 130 | + } | |
| 131 | + | |
| 132 | + if ($isBot) { | |
| 133 | + header('Location: /'); | |
| 134 | + exit(); | |
| 117 | 135 | } |
| 118 | 136 | |
| 119 | 137 | $auth = new Auth; |
変更
util.php
| @@ -44,6 +44,46 @@ | ||
| 44 | 44 | die(); |
| 45 | 45 | } |
| 46 | 46 | |
| 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 | + | |
| 47 | 87 | function base58btc_encode(string $bin): string { |
| 48 | 88 | $a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; |
| 49 | 89 | $base = 58; |
| @@ -113,8 +153,7 @@ | ||
| 113 | 153 | } |
| 114 | 154 | |
| 115 | 155 | function randstr(): string { |
| 116 | - srand((int)floor(time() / (60*60*24))); | |
| 117 | - $len = rand(1, 20); | |
| 156 | + $len = random_int(1, 20); | |
| 118 | 157 | return bin2hex(random_bytes($len)); |
| 119 | 158 | } |
| 120 | 159 | |
| @@ -178,7 +217,7 @@ | ||
| 178 | 217 | } |
| 179 | 218 | |
| 180 | 219 | 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); | |
| 182 | 221 | } |
| 183 | 222 | } |
| 184 | 223 |
| @@ -16,19 +16,27 @@ | ||
| 16 | 16 | <form action="/login" method="POST"> |
| 17 | 17 | {$ $username = randstr() $} |
| 18 | 18 | {$ $password = randstr() $} |
| 19 | + {$ $botUsername = randstr() $} | |
| 20 | + {$ $botPassword = randstr() $} | |
| 19 | 21 | <table> |
| 20 | 22 | <tbody> |
| 21 | 23 | <tr> |
| 22 | 24 | <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> | |
| 24 | 26 | </tr> |
| 25 | 27 | <tr> |
| 26 | 28 | <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> | |
| 28 | 30 | </tr> |
| 29 | 31 | <tr> |
| 30 | 32 | <td></td> |
| 31 | 33 | <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> | |
| 32 | 40 | <input type="hidden" id="csrf_token" name="csrf_token" value="{{ make_csrf_token() }}" /> |
| 33 | 41 | <button>サインイン</button> |
| 34 | 42 | </td> |
| @@ -18,6 +18,10 @@ | ||
| 18 | 18 | {$ $password = randstr() $} |
| 19 | 19 | {$ $passwordVerify = randstr() $} |
| 20 | 20 | {$ $email = randstr() $} |
| 21 | + {$ $botUsername = randstr() $} | |
| 22 | + {$ $botPassword = randstr() $} | |
| 23 | + {$ $botPasswordVerify = randstr() $} | |
| 24 | + {$ $botEmail = randstr() $} | |
| 21 | 25 | <table> |
| 22 | 26 | <tbody> |
| 23 | 27 | <tr> |
| @@ -39,6 +43,14 @@ | ||
| 39 | 43 | <tr> |
| 40 | 44 | <td></td> |
| 41 | 45 | <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> | |
| 42 | 54 | <input type="hidden" id="csrf_token" name="csrf_token" value="{{ make_csrf_token() }}" /> |
| 43 | 55 | <button>登録</button> |
| 44 | 56 | </td> |