あなたのログインインターフェースは本当に安全ですか?
https://juejin.im/post/6859214952704999438より転載
序文
プログラムの書き方を学ぶとき、コードの最初の行は ですhello world
。しかし、WEB の背景技術を学び始めると、多くの人が最初に行うのは、文章を書いてログインすることです。
しかし、職歴が比較的短い多くの学生にインタビューしたり、コミュニケーションを取ったりすると、多くの学生が履歴書に次のように書いているにもかかわらず、機能ロジックを理解しているだけで、セキュリティについてはあまり考慮していないことがわかりました负责项目的登录/注册功能模块的开发和设计工作
。この記事は主に雑談を目的としたものですが、ログインインターフェイスを設計する際には、機能の実現だけでなく、セキュリティの観点から考慮する必要があることについても説明します。
セキュリティリスク
強引な
Web サイトがパブリック ネットワークに公開されている限り、人々が標的にされる可能性は高くなります。さまざまな方法で Web サイトのユーザー名を取得した後、すべてを横断するプログラムを作成するという、シンプルで効果的な爆発方法を試してください
。正しいパスワードが見つかるまで、考えられるパスワード
疑似コードは次のとおりです。
# 密码字典
password_dict = []
# 登录接口
login_url = ''
def attack(username):
for password in password_dict:
data = {'username': username, 'password': password}
content = requests.post(login_url, data).content.decode('utf-8')
if 'login success' in content:
print('got it! password is : %s' % password)
では、この状況を防ぐにはどうすればよいでしょうか?
検証コード
賢い同級生が考えてくれた、パスワードエラーが一定回数に達すると認証コードの認証回数を増やすことができる!たとえば、ユーザーのパスワード エラーが 3 回に達した場合、ユーザーはログイン操作を続行するために画像認証コードを入力する必要があるように設定します。
疑似コードは次のとおりです。
fail_count = get_from_redis(fail_username)
if fail_count >= 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
success = do_login(username, password)
if not success:
set_redis(fail_username, fail_count + 1)
疑似コードでは同時実行性は考慮されておらず、実際の開発ではロックを考慮できます。
これにより、確かに一部の違法な攻撃をフィルタリングできますが、現在の OCR テクノロジーでは、通常の画像検証コードがロボットを効果的に阻止することは非常に困難です (私たちはこれによって多くの被害を受けてきました)。もちろん、サードパーティ企業が提供するスライド検証などの検証スキームをお金を出して購入することもできますが、それらは 100% 安全ではなく、クラックされる可能性があります (痛い教訓)。
ログイン制限
このとき、別の同級生が「異常なユーザーのログイン操作を直接制限できる。パスワードエラーが一定回数に達すると、ユーザーのログインを直接拒否し、一定時間後に復元する」と教えてくれた。たとえば、10 回のエラーでログインするようにアカウントを設定した場合、そのアカウントのすべてのログイン操作は 5 分以内に拒否されます。
疑似コードは次のとおりです。
fail_count = get_from_redis(fail_username)
locked = get_from_redis(lock_username)
if locked:
return error('拒绝登录')
if fail_count >= 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
success = do_login(username, password)
if not success:
set_redis(fail_username, fail_count + 1)
if fail_count + 1 >= 10:
# 失败超过10次,设置锁定标记
set_redis(lock_username, true, 300s)
うーん、これでユーザーのパスワードが爆破される問題は確かに解決できます。ただし、これには別のリスクが伴います。攻撃者が Web サイトのユーザー情報を取得することはできませんが、Web サイトのすべてのユーザーがログインできなくなる可能性があります。
攻撃者は、ログインするためにすべてのユーザー名 (ユーザー名が存在しない場合でも、ランダム) をループするだけで済みます。そうすると、これらのユーザーは永久にロックされ、通常のユーザーは Web サイトにログインできなくなります。
IP制限
ユーザー名を直接狙うことはできないので、IPベースで対処することになりますが、攻撃者のIPを直接ブロックすれば大丈夫です。特定の IP でのログイン インターフェイスの呼び出しエラー数が一定の数に達した場合、その IP でのログイン操作の実行を禁止するように設定できます。
疑似コードは次のとおりです。
ip = request['IP']
fail_count = get_from_redis(fail_ip)
if fail_count > 10:
return error('拒绝登录')
# 其它逻辑
# do something()
success = do_login(username, password)
if not success:
set_redis(fail_ip, true, 300s)
実際、niginx の電流制限モジュールでは、単位時間内の IP の訪問回数を制限するなど、IP に対して多くの電流制限が行われています。
しかし、ここにはまだ問題があります。
- 例えば、現在多くの学校や企業が同じエクスポートIPを使用しているため、IPで直接制限すると他の一般ユーザーを誤って殺してしまう可能性があります。
- 現在、VPN が非常に多くなっているため、攻撃者は IP がブロックされた後に VPN を切り替えて攻撃することができます。
電話認証
それを防ぐもっと良い方法はないでしょうか?もちろんあります。近年、ほぼすべてのアプリケーションでユーザーが携帯電話をバインドする必要があることがわかります。1 つは国家の実名政策の要件であり、もう 1 つは携帯電話は基本的に個人を表すことができる ID カードと基本的に同じであるためです。身元。そのため、多くのセキュリティ運用は携帯電話認証に基づいており、ログインも可能です。
- ユーザーがパスワードを 3 回以上入力する場合、ユーザーは認証コードの入力を求められます (スライディング認証を使用することをお勧めします)。
- ユーザーがパスワードを 10 回以上入力すると、携帯電話認証がポップアップ表示され、ユーザーは携帯電話認証コードとパスワードの二重認証を使用してログインする必要があります。
携帯電話の認証コードのスワイプ防止も別の問題ですが、ここでは詳しく説明しません。認証コードのスワイプ防止に関して私たちが行ったことについては、後で時間があるときにお話します。
疑似コードは次のとおりです。
fail_count = get_from_redis(fail_username)
if fail_count > 3:
if captcha is None:
return error('需要验证码')
check_captcha(captcha)
if fail_count > 10:
# 大于10次,使用验证码和密码登录
if dynamic_code is None:
return error('请输入手机验证码')
if not validate_dynamic_code(username, dynamic_code):
delete_dynamic_code(username)
return error('手机验证码错误')
success = do_login(username, password, dynamic_code)
if not success:
set_redis(fail_username, fail_count + 1)
上記のいくつかの方法を組み合わせ、携帯電話認証コードの認証モードを追加しました。これにより、基本的にかなりの数の悪意のある攻撃者を防ぐことができます。しかし、絶対に安全なシステムはなく、攻撃者の攻撃コストを可能な限り増やすことしかできません。ウェブサイトの実際の状況に応じて、適切な戦略を選択できます。
中間者攻撃
中間者攻撃(略称MITM)とは、簡単に言うと、AとBの間の通信過程において、攻撃者がAとBの通信内容を盗聴や傍受によって取得または改ざんすることです。
栗を取る:宅配便を送る小白
には小黄
、途中で宅配便ポイント A を通過する必要がある小黑
ため、宅配便ポイント A に隠れるか、宅配便ポイント B を開いて宅配便ポイント A のふりをします。それから私はこっそり小白
宅配便を開けて小黄
、中身を確認しました。小白
宅配サービスをやめて、自分で 10 セント硬貨のような箱を梱包することもできます小黄
。
ログイン プロセス中に、攻撃者がクライアントからサーバーに送信されるログイン リクエストを盗聴すると、ユーザーのユーザー名とパスワードを簡単に入手できます。
HTTPS
中間者攻撃を防ぐための最も簡単かつ効果的な操作は、HTTPS を置き換え、Web サイト内のすべての HTTP リクエストを変更して HTTPS の使用を強制することです。
HTTPS が中間者攻撃を防ぐことができるのはなぜですか?
HTTPS は実際に、HTTP プロトコルと TCP プロトコルの間に SSL/TLS プロトコルを追加して、データの安全な送信を保証します。HTTP と比較して、HTTPS には主に次の特徴があります。
- コンテンツの暗号化
- データの整合性
- 認証
特定の HTTPS 原則はここでは拡張されません。BAIDU は自分で行うことができます
暗号化された送信
HTTPS に加えて、機密データの送信を手動で暗号化することもできます。
- ユーザー名は、非対称暗号化を使用してクライアント側で暗号化し、サーバー側で復号化できます。
- パスワードの平文が公開されるのを防ぐために、クライアントが MD5 を実行した後にパスワードを送信できます。
他の方法
上記で説明したことに加えて、実際には次のような他の仕事が考えられます。
- 操作ログ、ユーザーの各ログインおよび機密操作を記録する必要があります (IP、デバイスなどを含む)
- 異常操作やログインリマインダー上記の操作ログを取得することで、ログに基づいてリスクリマインダーを作成することができ、例えば、ユーザーが異常ログインした場合、パスワードを変更した場合、または異常ログインした場合に、テキストメッセージを送信してユーザーに注意を促すことができます。
- 弱いパスワードを拒否する パスワードを登録または変更する際に、ユーザーは弱いパスワードを設定できません。
- ユーザー名の通過を防止する 一部の Web サイトでは、登録時にユーザー名を入力した後、そのユーザー名が存在するかどうかを確認するメッセージが表示されます。この方法では、Web サイトのすべてのユーザー名が漏洩する (インターフェイスを通過するだけで) というリスクが発生するため、対話やロジックを制限する必要があります。
- ...
追記
現在、この国ではさまざまな法律が導入され続けており、ユーザーのデータはますます重要になっています。開発者として、ユーザー データとユーザー プライバシーを保護するためにさらに努力する必要もあります。後ほど、データ セキュリティに関して当社がどのような取り組みを行ってきたかについてお話しさせていただきます。少しでもお役に立てれば幸いです。