2

In my project an User can create a Customer and assigning it zero or more Tag. These entities have a relation with User of course. This is done by a form that has a tag field of entity type, filtered by current logged user:

$user = $this->securityContext->getToken()->getUser();

$builder
    ->add('tags', 'meta_selector', array(
        'label'         => 'Tag',
        'class'         => 'Acme\HelloBundle\Entity\Tag',
        'property'      => 'select_label',
        'query_builder' => function(EntityRepository $er) use($user) {
            $qb = $er->createQueryBuilder('t');

            return $qb
                ->where($qb->expr()->eq('t.user_id', ':user')
                ->orderBy('t.name')
                ->setParameter('user', $user);
        }
    ))
;

And this is working fine. Looking at a generated HTML tags are rendered as checkboxes:

<div class="controls">
    <label class="checkbox">
        <input type="checkbox" value="2" name="customer[tags][2]"
            id="customer_tags_2"> A Tag
    </label>
    <label class="checkbox">
        <input type="checkbox" value="3" name="customer[tags][3]" 
            id="customer_tags_3"> Another Tag
    </label>
</div>

I'd like to investigate further about form tampering. In particular making a POST request from a trusted user adding customer%5Btags%5D%5B1%5D=1, that is a tag with id equal to 1 which exists but it has been created by another user. Attacker user is creating an customer with a tag created by another user:

POST http://localhost/Symfony2/web/app_dev.php/app/customers/new HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost/Symfony2/web/app_dev.php/app/customers/new
Cookie: PHPSESSID=3avu1a2a1eufthr5tdftuhrnn7; hl=it
Content-Type: application/x-www-form-urlencoded
Content-Length: 276

customer%5Bfirst%5D=fake&customer%5Blast%5D=fake&customer%5Bgender%5D=m&customer%5Bbirthday%5D=&customer%5Bemail%5D=&customer%5Bmobile%5D=&customer%5Baddress%5D=&customer%5Bcountry%5D=IT&customer%5Btags%5D%5B1%5D=1&customer%5B_token%5D=455783fa2f866677669c9034a90554b9f75d68b4

.. and seems there is some sort of control that prevents this. Result is 200 OK (should be a 302 in case of success) without any error and form is rendered again. Of course entity is not persisted.

Actual question is: how Symfony 2 protect from this kind of form "tampering" attacks? A possible explanation is the it checks that submitted tags exist inside the collection returned by the form builder. But a reference is needed...

EDIT: even disabling CSRF protection the result is the same. By the way i was passing a valid token and CSRF is intended to protect from other types of attacks.

4

2 に答える 2

2

あなたの質問への答えは非常に簡単に説明することができます。すべての選択フィールド(およびエンティティタイプは選択タイプの特殊化です)には、選択肢のリストがあります。選択肢ごとに、フィールドは

  • 選択したモデル表現(「選択」)(Tagインスタンスなど)
  • 選択したビュー表現(「値」)(IDなど)
  • ビューで使用されるラベル(例:のプロパティTag

フォームを送信すると、選択フィールドはこのリストで、送信されたビュー表現と一致するモデル表現を検索します。何も見つからない場合、フィールドは未割り当てのままです。

このロジックのコードは、ChoiceListクラスとその子孫(この場合はEntityChoiceList )にあります。送信すると、メソッドgetChoicesForValues()が実行され、ルックアップが実行され、速度が最適化されます。

于 2012-07-28T07:30:08.940 に答える
0

大雑把な推測: CSRF 保護が有効になっており、エラーをレンダリングしません。

于 2012-07-12T13:41:31.927 に答える