2

PagSeguro (支払いゲートウェイ - ブラジル版の PayPal) を自分のサイトに取り込もうとしています。顧客は PagSeguro の使用を終了した後、私が指定した関数に (POST 経由で) データを送信します。ただし、POST を受信して​​いません。考えられるすべてのトラブルシューティングを行った後、PagSeguro に連絡しました。彼らのログは、POST は通常どおり送信されているが、HTTP 302 応答を受信して​​いることを示していると述べています。

なぜこれが起こっているのかを理解するために、非表示の値を持つフォームを作成して、関数への POST の送信をシミュレートしました。何か関係がある場合に備えて、このフォームを別のドメインに置きました。シミュレーション フォームから POST を送信するたびに、HTTP 200 応答を受け取り、POST が受信されたことをログに示します。

PagSeguro が私のシミュレーションとは異なる応答を受け取る可能性があるのはなぜですか? サーバーと関係がありますか、それとも私のスクリプトと関係がありますか?

POST を受信する関数 (CodeIgniter を使用) は次のとおりです。

function pagseguro_retorno(){
    if (count($_POST) == 0) {
        return FALSE;
    }
    $msg = 'POST RECEIVED';
    $simulate = $this->input->post('Simulate');
    if ( ! empty($simulate)){
        $result = 'VERIFICADO';
        $msg .= ' FROM SIMULATOR';
    } else {
        $this->load->library(PagSeguroNpi);
        $result = $this->PagSeguroNpi->notificationPost();
    }
    $this->log($msg);
    if ($result == "VERIFICADO") {
        $id = $this->input->post('Referencia');//cart id
        $this->load->model('transacao_model');
        $trans_row = $this->transacao_model->get_transaction($id);
        if ( ! is_object($trans_row)){
            //LOAD NEW TRANSACTION
            if ( ! $this->new_transaction($id)){
                $notice = "Unable to load new transaction</p><p>";
                $this->log($notice);
                $notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
                $this->email_notice($notice);
            }
        }
        $this->load->model('carrinho_model');
        if($_POST['StatusTransacao'] == 'Aprovado'){
            $status = 'apr';
        }elseif($_POST['StatusTransacao'] == 'Em Análise'){
            $status = 'anl';
        }elseif($_POST['StatusTransacao'] == 'Aguardando Pagto'){
            $status = 'wtg';
        }elseif($_POST['StatusTransacao'] == 'Completo'){
            $status = 'cmp';
            //nothing more happens here - client must click on 'mark as shipped' before cart is removed and history data is loaded
        }elseif($_POST['StatusTransacao'] == 'Cancelado'){
            //reshelf - don't set $status, because the cart's about to be destroyed
            $this->carrinho_model->reshelf(array($id));
        }
        if (isset($status)){
            $this->carrinho_model->update_carrinho($id, array('status' => $status));
        }
    } else if ($result == "FALSO") {
        $notice = "PagSeguro return was invalid.";
        $this->log($notice);
        $notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
        $this->email_notice($notice);
    } else {
        $notice = "Error in PagSeguro request";
        $this->log($notice);
        $notice .= '<pre>'.print_r($_POST, TRUE).'</pre>';
        $this->email_notice($notice);
    }
}

セキュリティ更新:

投稿した後、すぐに自分がハッキングの試みに心を開いていることに気付きました。関数は必ずパブリックにする必要があるため、関数の名前を知っている人は誰でも関数にアクセスして「シミュレート」を投稿して、すぐに検証を取得できます。その後、必要なデータを渡すことができました。

関数の名前を推測できない名前に変更し、本番モードでないときはシミュレート オプションを無効にしました。

4

1 に答える 1

0

問題は、適切な CSRF コードが POST で送信されない場合、私の CSRF 保護がリダイレクトを引き起こすことでした。問題のサイトで作成した動的シミュレーターによって生成された HTML をコピーしたため、シミュレーターは機能していました。次に、HTML を貼り付けて静的シミュレーターを作成し、別の URL に配置しました。HTML とともに、うっかり CSRF コードも貼り付けてしまいました。静的シミュレーターは、コードの有効期限が切れるまで正常に機能しました。数回使用をやめたので、今日まで機能していないことに気づきませんでした。

この正確なシナリオが今後 500 年以内に再び発生することはないことはわかっていますが、POST を受信する機能を無効にしないと、CSRF セキュリティなどによって支払いゲートウェイなどの問題が発生する可能性があります。

于 2012-11-24T12:33:50.660 に答える