Bug(バグ) #3232
OAuth のアクセストークンを取得していくる際にシークレットキーを用いた署名を検証できない
0%
Description
概要¶
OAuth のアクセストークンを取得していくる際にシークレットキーを用いた署名を検証できない.
クライアントは通常アクセストークンを取得してくる際に,事前に生成されているリクエストトークンとリクエストトークンのシークレットを用いて署名を行なう.しかし,クライアント側で正しいシークレットを用いた署名の実装を行なっていても,署名の検証に失敗してアクセストークンが取得できない.
原因¶
サーバ側では下記コード部のように,リクエストトークンを取得してくる際にシークレット部分を空文字列としており,このトークンオブジェクトを用いて署名を検証してしまう.
そのため,おそらくシークレットが空文字列であるトークンオブジェクトとして署名の検証を行なってしまうとおもわれるため,クライアントの実装がシークレットを空にするようになっている場合には成功するものと思われる.
(コードは 3.6.6 のもの)
lib/action/opOAuthTokenAction.class.php 86 行目
75 public function executeAccessToken(sfWebRequest $request) 76 { 77 require_once 'OAuth.php'; 78 79 $authRequest = OAuthRequest::from_request(); 80 $requestToken = $authRequest->get_parameter('oauth_token'); 81 $this->information = $this->getTokenTable()->findByKeyString($requestToken); 82 $this->forward404Unless($this->information); 83 $this->forward404Unless($this->information->getIsActive()); 84 $this->forward404Unless($this->information->getVerifier() === $authRequest->get_parameter('oauth_verifier')); 85 86 $token = $this->getServer()->fetch_access_token($authRequest); 87 88 $this->information->delete(); 89 90 $this->getResponse()->setContent((string)$token); 91 92 return sfView::NONE; 93 }
lib/vendor/OAuth/OAuth.php 470 行目
460 /** 461 * process an access_token request 462 * returns the access token on success 463 */ 464 public function fetch_access_token(&$request) { 465 $this->get_version($request); 466 467 $consumer = $this->get_consumer($request); 468 469 // requires authorized request token 470 $token = $this->get_token($request, $consumer, "request"); 471 472 473 $this->check_signature($request, $consumer, $token); 474 475 $new_token = $this->data_store->new_access_token($token, $consumer); 476 477 return $new_token; 478 }
lib/vendor/OAuth/OAuth.php 548 行目
543 /** 544 * try to find the token for the provided request's token key 545 */ 546 private function get_token(&$request, $consumer, $token_type="access") { 547 $token_field = @$request->get_parameter('oauth_token'); 548 $token = $this->data_store->lookup_token( 549 $consumer, $token_type, $token_field 550 ); 551 if (!$token) { 552 throw new OAuthException("Invalid $token_type token: $token_field"); 553 } 554 return $token; 555 }
lib/util/opOAuthDataStore.class.php 110 行目
105 public function lookup_token($consumer, $token_type, $token) 106 { 107 $tokenRecord = $this->getTokenTable()->findByKeyString($token, $token_type, $this->queryTemplate); 108 if ($tokenRecord) 109 { 110 $token = new OAuthToken($tokenRecord->getKeyString(), ''); 111 if ('request' !== $token_type) 112 { 113 $token->secret = $tokenRecord->getSecret(); 114 } 115 return $token; 116 } 117 118 return null; 119 }
修正案¶
lib/util/opOAuthDataStore.class.php 110 行目の空文字列のシークレットではないものを返す.
ただし,そのまま修正してしまうと既存の OpenPNE OAuth クライアントに影響が出るため,シークレットがある場合とない場合での署名の検証を行い,メジャーバージョンアップ時にシークレットがない場合の検証を取り除くという対応が考えられる.
この対応を行う場合にはメジャーバージョンアップ時に確認できるチケットを作成しておく必要が有る.
Related issues
Associated revisions
(fixes #3232) fixed to get secret key when request token was looked up in datastore
History
#1
Updated by Yuya Watanabe over 10 years ago
- Description updated (diff)
#2
Updated by Yuya Watanabe over 10 years ago
- Description updated (diff)
#3
Updated by Yuya Watanabe over 10 years ago
- Status changed from New(新規) to Accepted(着手)
- Assignee set to Yuya Watanabe
#4
Updated by Yuya Watanabe over 10 years ago
- Status changed from Accepted(着手) to Pending Review(レビュー待ち)
- % Done changed from 0 to 50
更新履歴 978cb7c92e9d4f10b0b7a8d3d469a63af980c0fa で適用されました。
#5
Updated by Yuya Watanabe over 9 years ago
https://tools.ietf.org/html/rfc5849#section-2.1
When making the request, the client authenticates using only the
client credentials. The client MAY omit the empty "oauth_token"
protocol parameter from the request and MUST use the empty string as
the token secret value.
#6
Updated by isao sano over 8 years ago
- Copied to Backport(バックポート) #3705: OAuth のアクセストークンを取得していくる際にシークレットキーを用いた署名を検証できない added
#7
Updated by isao sano over 8 years ago
- Copied to Backport(バックポート) #3706: OAuth のアクセストークンを取得していくる際にシークレットキーを用いた署名を検証できない added
#8
Updated by kaoru n over 7 years ago
- Assignee deleted (
Yuya Watanabe)
#9
Updated by Youichi Kimura over 6 years ago
- Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
- Assignee set to Youichi Kimura
- % Done changed from 50 to 70
- 3.6 で発生するか changed from Unknown (未調査) to Yes (はい)
- 3.8 で発生するか changed from Unknown (未調査) to Yes (はい)
元のコードで opOAuthDataStore::lookup_token()
で $token_type
が 'request'
の場合のみ token_secret を空文字列にする実装となっているのは、OAuth 1.0a でのリクエストトークン取得時には署名に空の token_secret が使われることを意識したものではないかと思います。
しかし実際には、リクエストトークン取得時は常に新規のトークンを発行するため OAuthDataStore::lookup_token()
が呼ばれることはありません。
一方で OAuthDataStore::lookup_token()
でリクエストトークンを要求される場面はさらに後のアクセストークン取得時であり、この時点では request_secret を使用した署名が行われています。ここで token_secret を空文字列に書き換えてしまうと、クライアントが生成した署名と検証のために生成した署名が一致しないことになってしまいます。
よって、そもそも OAuthDataStore::lookup_token()
を実装する上で token_secret を空にする処理は不要であり、DB から取得したトークンの組をそのまま返せばよいことになります。
以上のことから今回の不具合は 978cb7c9 の修正で問題ないと判断しました。
#10
Updated by Youichi Kimura over 6 years ago
下記の手順で動作確認できます (https://gist.github.com/upsilon/9a3ad8fb319276519ef90abe5f472235 を使用する):
$ wget https://github.com/openpne/OpenPNE3/raw/OpenPNE-3.8.20/lib/vendor/OAuth/OAuth.php $ wget https://gist.github.com/upsilon/9a3ad8fb319276519ef90abe5f472235/raw/25ad4b89a529e0235436cbcbdad557645eb7215f/apitest.php $ vim apitest.php # BASE_URL, CONSUMER_KEY, CONSUMER_SECRET を書き換え $ php apitest.php Authorize URL: http://sns.example.com/pc_backend.php/oauth/authorize?oauth_token=*** PIN Code > (Authorize URLにアクセスして表示されるPINコードを入力)
#11
Updated by isao sano almost 6 years ago
- Status changed from Pending Testing(テスト待ち) to Won't fix(対応せず)
- % Done changed from 70 to 0
OpenPNE 3.8.23 にて対応済みであったため、対応せずとします。