1

プロジェクトの1つでDjangoの組み込みユーザーモデルを使用しています。もちろん、ユーザーは編集可能である必要があります。これが最も便利なソリューションなので、Django独自のUserChangeFormを使用してユーザー編集用のフォームを提供し始めました。UserChangeFormは、基本的にUserModelのModelFormであるため、Userモデルのすべてのフィールドを変更できます。

ユーザーがすべてのフィールドを変更できるようにしたくありません。したがって、私の最初のアイデアは、UserChangeForm全体をテンプレートに渡し、必要なフィールド(たとえば、「username」と「email」)のみをレンダリングすることでした。また、スーパーユーザーのみがユーザー名を変更できるようにしたいので、このフィールドはスーパーユーザーの場合にのみ表示されます。

基本的なコードは次のようになります。

ビュー機能

def edit_user(request, pk):
    ...    #code to ensure not everyone can edit every user
    user = User.objects.get(pk=pk)
    if request.method == 'POST':
        form = UserChangeForm(request.POST, instance=user)
        if form.is_valid:
            form.save()
           ...    #redirect
    else:
        form = UserChangeForm(instance=user)
    ...    # render template

テンプレートのフォーム

<form action="{{ request.path }}" method="post">
    {% csrf_token %}
    {% if user.is_superuser %}
        {{ form.username }}
    {% endif %}
    {{ form.email }}
    <button type="submit">Save</button>
</form>

さて、私の質問は次のとおりです。このソリューションのセキュリティ面はどうですか?攻撃者がスーパーユーザーでなくても、たとえばユーザー名フィールドを追加するのを防ぐために私は何もしません。それによって、彼はPOSTデータに追加のデータを入力し、それがview関数に送信され、Userオブジェクトを更新するために使用されます。元のUserChangeFormにはフィールド'is_superuser'も含まれているため、これは非常に危険です。

私は自分の疑いをテストするために自分でフォームをハックしてみました。通常のユーザーとしてログインし、開発者ツールを使用してユーザー名の入力を追加し、フォームを送信しました。結果は例外でした:

Traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  20.                 return view_func(request, *args, **kwargs)
File "/Users/joker/Development/wiki2099/wiki2099/apps/accounts/views.py" in edit_user
  69.             form.save()
File "/Library/Python/2.7/site-packages/django/forms/models.py" in save
  364.                              fail_message, commit, construct=False)
File "/Library/Python/2.7/site-packages/django/forms/models.py" in save_instance
  74.                          " validate." % (opts.object_name, fail_message))

Exception Type: ValueError at /accounts/edit/12/
Exception Value: The User could not be changed because the data didn't validate.

それがこの種の攻撃が不可能なのか、それとも私が正しくやらなかったのかはわかりません。CSRFトークンはそのような種類のハッキングを防ぐことができると思いますが、ドキュメントにはその問題について何も見つかりませんでした。誰かが私を教えてもらえますか?攻撃者がレンダリングされていないフォームフィールドを使用するのを防ぐメカニズムはありますか?それはどのように機能しますか?

前もって感謝します!

4

2 に答える 2

1

私の知る限り、CSRFトークンはCSRF攻撃からのみ保護し、データを変更するためのアクセス許可については何もしません。

ユーザーがスーパーユーザーでない場合にフィールドをレンダリングしないだけなのか、それともまったく追加しなかったのかは明確ではありませんがself.fields。2番目の方法を使用するか、スーパーユーザー用に別のフォームを用意する必要があります。

于 2012-09-08T16:18:11.097 に答える
1

ユーザーが編集できるフィールドを制限する場合は、モデルのフィールドのサブセットを使用してフォームを定義する必要があります。

テンプレートにフォームフィールドをレンダリングせず、ユーザーがそのデータを送信した場合、Djangoは通常どおりにフォームフィールドを処理します。トレースバックを見て、なぜ失敗したのかわかりませんが、説明した方法を使用した攻撃は可能です。

csrf保護はここでは役に立ちません。その目的は、サードパーティがユーザーをだましてサイトにデータを送信させないようにすることであり、余分なフィールドを含む手作りのPOSTデータから保護することではありません。

テンプレートでフィールドを意図的にレンダリングしない場合は、注意すべき別の問題があります。省略されたフィールドが不要な場合、欠落しているPOST値は空の文字列として解釈され、検証され、データが消去されます。

于 2012-09-08T16:43:45.507 に答える