MTで学ぶセキュアプログラミング
MT  Tokyo  2014  August
junnama@alfasado.jp
何のために?
•サイトの改ざんを防ぐために  
•クライアントのセキュリティ要件を
満たすために  
•被害リスクをできるだけ少なくする
ために
何のために、誰が?
•セキュリティコンサルタントが  
•プログラマが  
•デザイナが  
•ディレクターが
何を?
•MTMLテンプレートを  
•Movable  Typeそのものを  
•MTプラグインを  
•MTベースのウェブサイトを
イントロダクション
<Tweet禁⽌止>
⼤大⼈人の事情につき削除
本題
</Tweet禁⽌止>
例例  :  PHPを出⼒力力するテンプレート
PHPを出⼒力力するテンプレート
これは果たして脆弱性か?
何をされたくないか
•情報の漏漏洩(権限のない情報
へのアクセス)  
•権限昇格=権限を越えた操作  
•情報の書き換え、削除
性善説か?  性悪説か?
攻撃するのは誰?
•悪意の第三者による外部から
のアタック  
•内部犯⾏行行(元社員、コミュニ
ティユーザー)  
•内部(犯⾏行行ではないが)誘発=>
正規のユーザーに踏ませる
そこまで許可した覚えはない。
いや、だって、できるんだ
から。。。
Vs.
この場合、どちらが悪いのか?
はともかく、セキュリティ監査
では、アウト。
基本、性悪説に基づく。
<MTEntryBody
replace=”<?”,””>
完璧に防げるか?  
(程度度問題→やらないより、まし)
AllowPHPScript 0
PowerCMS(DynamicMTMLでは)...
<MTStripPHP>
<MTEntryBody>
</MTStripPHP>
PowerCMS(DynamicMTMLでは)...
function strip_php( $source ) {!
$tokens = token_get_all( $source );!
$res = '';!
$inphp = FALSE;!
foreach ( $tokens as $t...
<MTEntryBody
replace=”<?”,””>
でも、やらないより遥かにまし
主なもの
•XSS  =  Cross  Site  Scripting  
•CSRF  =  Cross  site  request  
forgeries  
•SQL  (OS  Command)  Injection  
•Dire...
例例  :  検索索結果テンプレート
例例  :  検索索結果テンプレート
例例  :  検索索結果テンプレート
例例  :  検索索結果テンプレート
例例  :  検索索結果テンプレート
sub load_core_tags {!
require MT::Template::Context;!
return {!
function => {!
SearchString => &_hdlr_s...
例例  :  検索索結果テンプレート
sub prepare_context {!
my $app = shift;!
my $q = $app->param;!
...!
if ( my $str = $app->{search_string...
あまり宜しくない!(きっぱり)
例例  :  検索索結果テンプレート
...!
!
sub context_script {!
my ( $ctx, $args, $cond ) = @_;!
!
my $search_string!
= decode_html($ctx->...
•どこでエスケープ済みなのか、
わからなくなるぞ?  
•エンコード済みのクエリを渡さ
れたらおかしくならんか?
統⼀一されていないので、
責任が曖昧(忘れちゃう)
わからなくなるから...
わからなくなるから...
⼊入⼒力力値のエスケープは、  
テンプレート出⼒力力時に統⼀一
次
$q = $_GET[‘search’];!
$sql = “SELECT FROM
mt_entry WHERE!
mt_entry.entry_title LIKE %
${q}%”
例例  :  PHPによる実装
APIやORマッパを使え
my $app = MT->instance;!
my $q = $app->param(‘search’);!
my @entries = MT-
>model(‘entry’)!
->load( {!
title => { like => ...
$app = $ctx-
>stash(‘bootstrapper’);!
$q = $app->param(‘search’);!
$entries = $app->!
load(‘entry’,!
array( ‘title’ => !
a...
var q = jQuery('#search').value;!
var params = {!
search: q,!
searchFields: "title,body",!
};!
api.listEntries(siteId, par...
何かあったらメーカーのせいw
ユーザーの⼊入⼒力力を信⽤用しない!
そもそも
次
applications:!
cms:!
menus:!
page:page_foo:!
label: Foo!
order: 1000!
mode: page_foo!
permission: manage_pages!
view:!
- b...
例例  :  Pluginでのメソッドの拡張
methods:!
page_foo: $Foo::Foo::CMS:: page_foo!
package Foo::CMS!
!
sub page_foo {!
my $app = shift;...
例例  :  Pluginでのメソッドの拡張
短縮URLでもメールで送り
つけてやれ!
やっちゃえ!(*)
脱線  :  管理理画⾯面にBasic認証かけても、正規
ユーザー攻撃タイプには意味がないよね。
新規作成
編集
削除
例例  :  Pluginで独⾃自オブジェクト
え?
sub  save  {  
        my  $app    =  shift;  
        my  $q        =  $app-‐‑‒>param;  
        my  $type  =  $q-‐‑‒>par...
対策
程度度問題=読み出されるだけより、改ざ
んされるほうが  い・や・だ。
ちょっと脱線。何故ここだけ対策を?
セキュリティにおいて、「程度度問題」
はいつもつきまとう。
但し、前提は事情に
よって変わる
例例えば、個⼈人情報。  
流流出も改ざんもどっちもどっち
改めて対策
package  MT::App::CMS;
ホワイトリストではなくブラックリスト
なので、不不要なものは塞塞いでおく
GETリクエストは弾く(気休めだが)
package Foo::CMS!
!
sub page_foo {!
my $app = shift;!
if ( $app->request_method ne “POST” ) { !
return ...
⼀一時トークンのチェック
package Foo::CMS!
!
sub page_foo {!
my $app = shift;!
if $app->validate_magic!
or return $app->permission_den...
⼀一時トークンのチェック
•magic_̲token=アクティブユーザーの
session情報  
•saveやdelete等の操作ではチェックを!  
•(但し)magic_̲tokenが無効もしくは空の
時、ID/Password⼊入⼒力力...
⼀一時トークンのチェック
•magic_̲token=アクティブユーザーの
session情報  
•saveやdelete等の操作ではチェックを!  
•(但し)magic_̲tokenが無効もしくは空の
時、ID/Password⼊入⼒力力...
でも
CSRFとしては、不不⼗十分ではないか?
mt.cgi?_̲_̲mode=save&_̲type=foo&title=Title...
クリックしちゃだめー!
悪意のURL
改善案
if $app->validate_magic(!
{ with_confirm!
=> { message =>!
ʻ‘FooをBarしようとしています。  
                                     ...
改善案(簡易易指定)
if $app->validate_magic!
( ʻ‘FooをBarしようとしています。宜しいですか?ʼ’ )!
or return $app->trans_error...!
}!
改善案(次に何が起こるのかを明⽰示する)
FooをBarしようとして  
います。宜しいですか?
これからはセキュリティだっ
て、UX重視だろ!
話しを戻します
package Foo::CMS!
!
sub page_foo {!
my $app = shift;!
my $perms = $app->permissions!
or return $app->permission_denied();!...
例例題
sub  some_̲action{  
        my  $app=  shift;  
        require  MT::Page;  
        my  $blog  =  app-‐‑‒>blog;  
      ...
1.パラメタidに数字以外のものが渡された場合  
2.パラメタidにpageオブジェクトではなく
entryオブジェクトのidが渡された場合  
3.パラメタidが空の場合  
4.パラメタidに現在のblogに属さないentry/
page...
sub  some_̲action{  
        my  $app=  shift;  
        require  MT::Page;  
        my  $blog  =  app-‐‑‒>blog;  
      ...
添削後
sub  some_̲action  {  
        my  $app  =  shift;  
        $app-‐‑‒>validate_̲magic(  ʻ‘FooをBarしてもよろしいですか?ʼ’  )  or  
  ...
       if  (!  $app-‐‑‒>can_̲do(  'manage_̲pages'  )  )  {  
                return  $app-‐‑‒>trans_̲error(  'Permission  ...
⼀一気に難易易度度あがりましたが...
結論論
まとめ
•セキュアプログラミングは性悪説  
•それでも程度度問題。何をやられない
ようにするか。何を優先するか(何
は、あきらめるか)  
•セキュリティにもUXの視点が必要
まとめ
•ユーザーの⼊入⼒力力を信⽤用しない  
•エスケープは出⼒力力時に統⼀一する  
•SQLを⾃自前で書くな。API使え  
•正規ユーザー攻撃型改ざん対策のた
めに、⼀一時トークンを使う
ありがとうございました。
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
MTで学ぶセキュアプログラミング@MT Tokyo
Upcoming SlideShare
Loading in …5
×

MTで学ぶセキュアプログラミング@MT Tokyo

1,361 views

Published on

MT東京 8月 テーマセキュリティのセッション

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,361
On SlideShare
0
From Embeds
0
Number of Embeds
322
Actions
Shares
0
Downloads
4
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

MTで学ぶセキュアプログラミング@MT Tokyo

  1. 1. MTで学ぶセキュアプログラミング MT  Tokyo  2014  August junnama@alfasado.jp
  2. 2. 何のために? •サイトの改ざんを防ぐために   •クライアントのセキュリティ要件を 満たすために   •被害リスクをできるだけ少なくする ために
  3. 3. 何のために、誰が? •セキュリティコンサルタントが   •プログラマが   •デザイナが   •ディレクターが
  4. 4. 何を? •MTMLテンプレートを   •Movable  Typeそのものを   •MTプラグインを   •MTベースのウェブサイトを
  5. 5. イントロダクション <Tweet禁⽌止>
  6. 6. ⼤大⼈人の事情につき削除
  7. 7. 本題 </Tweet禁⽌止>
  8. 8. 例例  :  PHPを出⼒力力するテンプレート
  9. 9. PHPを出⼒力力するテンプレート
  10. 10. これは果たして脆弱性か?
  11. 11. 何をされたくないか •情報の漏漏洩(権限のない情報 へのアクセス)   •権限昇格=権限を越えた操作   •情報の書き換え、削除
  12. 12. 性善説か?  性悪説か?
  13. 13. 攻撃するのは誰? •悪意の第三者による外部から のアタック   •内部犯⾏行行(元社員、コミュニ ティユーザー)   •内部(犯⾏行行ではないが)誘発=> 正規のユーザーに踏ませる
  14. 14. そこまで許可した覚えはない。 いや、だって、できるんだ から。。。 Vs.
  15. 15. この場合、どちらが悪いのか? はともかく、セキュリティ監査 では、アウト。 基本、性悪説に基づく。
  16. 16. <MTEntryBody replace=”<?”,””>
  17. 17. 完璧に防げるか?   (程度度問題→やらないより、まし)
  18. 18. AllowPHPScript 0 PowerCMS(DynamicMTMLでは)...
  19. 19. <MTStripPHP> <MTEntryBody> </MTStripPHP> PowerCMS(DynamicMTMLでは)...
  20. 20. function strip_php( $source ) {! $tokens = token_get_all( $source );! $res = '';! $inphp = FALSE;! foreach ( $tokens as $token ) {! if ( is_string( $token ) ) {! $token = array( '', $token );! }! list( $id, $str ) = $token;! if (! $inphp ) {! if ( $id === T_OPEN_TAG or $id == T_OPEN $inphp = TRUE;! } else {! $res .= $str;! }! 厳密には、PHPはPHPで評価する
  21. 21. <MTEntryBody replace=”<?”,””> でも、やらないより遥かにまし
  22. 22. 主なもの •XSS  =  Cross  Site  Scripting   •CSRF  =  Cross  site  request   forgeries   •SQL  (OS  Command)  Injection   •Directory  traversal
  23. 23. 例例  :  検索索結果テンプレート
  24. 24. 例例  :  検索索結果テンプレート
  25. 25. 例例  :  検索索結果テンプレート
  26. 26. 例例  :  検索索結果テンプレート
  27. 27. 例例  :  検索索結果テンプレート sub load_core_tags {! require MT::Template::Context;! return {! function => {! SearchString => &_hdlr_search_string,! ...! ! sub _hdlr_search_string! { $_[0]->stash('search_string') || '' } package MT::Template::Context::Search;!
  28. 28. 例例  :  検索索結果テンプレート sub prepare_context {! my $app = shift;! my $q = $app->param;! ...! if ( my $str = $app->{search_string} ) {! $ctx->stash(! 'search_string', encode_html($str) );! } package MT::App::Search;! コード中でエスケープしてる
  29. 29. あまり宜しくない!(きっぱり)
  30. 30. 例例  :  検索索結果テンプレート ...! ! sub context_script {! my ( $ctx, $args, $cond ) = @_;! ! my $search_string! = decode_html($ctx->stash('search_string') package MT::Template::Context::Search;! わざわざ戻してんのかよ!
  31. 31. •どこでエスケープ済みなのか、 わからなくなるぞ?   •エンコード済みのクエリを渡さ れたらおかしくならんか?
  32. 32. 統⼀一されていないので、 責任が曖昧(忘れちゃう)
  33. 33. わからなくなるから...
  34. 34. わからなくなるから...
  35. 35. ⼊入⼒力力値のエスケープは、   テンプレート出⼒力力時に統⼀一
  36. 36.
  37. 37. $q = $_GET[‘search’];! $sql = “SELECT FROM mt_entry WHERE! mt_entry.entry_title LIKE % ${q}%” 例例  :  PHPによる実装
  38. 38. APIやORマッパを使え
  39. 39. my $app = MT->instance;! my $q = $app->param(‘search’);! my @entries = MT- >model(‘entry’)! ->load( {! title => { like => $q }, ! } ) 例例  :  Perlによる実装
  40. 40. $app = $ctx- >stash(‘bootstrapper’);! $q = $app->param(‘search’);! $entries = $app->! load(‘entry’,! array( ‘title’ => ! array( ‘like’ => $q ))); 例例  :  PHP(DynamicMTML)による実装
  41. 41. var q = jQuery('#search').value;! var params = {! search: q,! searchFields: "title,body",! };! api.listEntries(siteId, params, function(response) {! if (response.error) {! return;! }! 例例  :  JavaScriptによる実装
  42. 42. 何かあったらメーカーのせいw
  43. 43. ユーザーの⼊入⼒力力を信⽤用しない! そもそも
  44. 44.
  45. 45. applications:! cms:! menus:! page:page_foo:! label: Foo! order: 1000! mode: page_foo! permission: manage_pages! view:! - blog! - website! 例例  :  Pluginでのメソッドの拡張
  46. 46. 例例  :  Pluginでのメソッドの拡張 methods:! page_foo: $Foo::Foo::CMS:: page_foo! package Foo::CMS! ! sub page_foo {! my $app = shift;! # Do Something! <= え?! }!
  47. 47. 例例  :  Pluginでのメソッドの拡張 短縮URLでもメールで送り つけてやれ! やっちゃえ!(*)
  48. 48. 脱線  :  管理理画⾯面にBasic認証かけても、正規 ユーザー攻撃タイプには意味がないよね。
  49. 49. 新規作成 編集 削除 例例  :  Pluginで独⾃自オブジェクト
  50. 50. え?
  51. 51. sub  save  {          my  $app    =  shift;          my  $q        =  $app-‐‑‒>param;          my  $type  =  $q-‐‑‒>param('_̲type');          my  $save_̲mode  =  'save_̲'  .  $type;          if  (  my  $hdlrs  =  $app-‐‑‒>handlers_̲for_̲mode($save_̲mode)  )  {                  return  $app-‐‑‒>forward($save_̲mode);}          my  $id  =  $q-‐‑‒>param('id');          $app-‐‑‒>validate_̲magic()  or  return;          my  $author  =  $app-‐‑‒>user;          my  $perms  =  $app-‐‑‒>permissions;          if  (  !$author-‐‑‒>is_̲superuser  )  {                  if  (  (  $type  ne  'author'  )  &&  (  $type  ne  'template'  )  ){                          return  return  $app-‐‑‒>permission_̲denied()  if  !$perms  &&  $id;                  }                  $app-‐‑‒>run_̲callbacks(  'cms_̲save_̲permission_̲filter.'  .  $type,                  $app,  $id  )  ||  return  $app-‐‑‒>permission_̲denied();          }   #以下、保存 MT::CMS::Common::save(⼀一部省省略略) magic_̲tokenを チェック save_̲fooメソッドが定義され ているときはそちらへforward システム管理理者の場 合、ここはスルー コールバックcms_̲save_̲permission_̲filter.fooが1以外を返すと権限エラー
  52. 52. 対策
  53. 53. 程度度問題=読み出されるだけより、改ざ んされるほうが  い・や・だ。 ちょっと脱線。何故ここだけ対策を? セキュリティにおいて、「程度度問題」 はいつもつきまとう。
  54. 54. 但し、前提は事情に よって変わる 例例えば、個⼈人情報。   流流出も改ざんもどっちもどっち
  55. 55. 改めて対策
  56. 56. package  MT::App::CMS; ホワイトリストではなくブラックリスト なので、不不要なものは塞塞いでおく
  57. 57. GETリクエストは弾く(気休めだが) package Foo::CMS! ! sub page_foo {! my $app = shift;! if ( $app->request_method ne “POST” ) { ! return $app->permission_denied();! }! #Do Something! } POSTしか受け付けない
  58. 58. ⼀一時トークンのチェック package Foo::CMS! ! sub page_foo {! my $app = shift;! if $app->validate_magic! or return $app->permission_denied();! }! #Do Something! } magic_̲tokenパラメタをチェック
  59. 59. ⼀一時トークンのチェック •magic_̲token=アクティブユーザーの session情報   •saveやdelete等の操作ではチェックを!   •(但し)magic_̲tokenが無効もしくは空の 時、ID/Password⼊入⼒力力画⾯面を表⽰示   •この時↑deleteメソッド以外ではパラメ タが引き継がれる
  60. 60. ⼀一時トークンのチェック •magic_̲token=アクティブユーザーの session情報   •saveやdelete等の操作ではチェックを!   •(但し)magic_̲tokenが無効もしくは空の 時、ID/Password⼊入⼒力力画⾯面を表⽰示   •この時↑deleteメソッド以外ではパラメ タが引き継がれる
  61. 61. でも
  62. 62. CSRFとしては、不不⼗十分ではないか? mt.cgi?_̲_̲mode=save&_̲type=foo&title=Title... クリックしちゃだめー! 悪意のURL
  63. 63. 改善案 if $app->validate_magic(! { with_confirm! => { message =>! ʻ‘FooをBarしようとしています。                                                      宜しいですか?ʼ’,! icon => ‘CAUTION’! } } )! or return $app->trans_error...! }!
  64. 64. 改善案(簡易易指定) if $app->validate_magic! ( ʻ‘FooをBarしようとしています。宜しいですか?ʼ’ )! or return $app->trans_error...! }!
  65. 65. 改善案(次に何が起こるのかを明⽰示する) FooをBarしようとして   います。宜しいですか?
  66. 66. これからはセキュリティだっ て、UX重視だろ!
  67. 67. 話しを戻します
  68. 68. package Foo::CMS! ! sub page_foo {! my $app = shift;! my $perms = $app->permissions! or return $app->permission_denied();! return $app->permission_denied()! unless $perms! ->can_do('edit_all_pages');! #Do Something! } ちゃんと権限をチェック +更更新が必要なものは権限をチェック
  69. 69. 例例題
  70. 70. sub  some_̲action{          my  $app=  shift;          require  MT::Page;          my  $blog  =  app-‐‑‒>blog;          my  $page  =  MT::Page-‐‑‒>load(  $app-‐‑‒>param(  'id'  )  );          if  (!  $page  )  {                  return  $app-‐‑‒>translate(  'Invalid  Page  ID:[_̲1].',  $app-‐‑‒>param(  'id'  )  );          }          my  $perm  =  $app-‐‑‒>user-‐‑‒>is_̲superuser;          if  (!  $perm  )  {                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲administer_̲website                $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲administer_̲blog                                              unless  $perm;                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲manage_̲pages                  unless  $perm;          }          if  (!  $perm  )  {                  return  $app-‐‑‒>translate(  'Permission  denied.'  );          }          #  この後、$pageへの処理理}
  71. 71. 1.パラメタidに数字以外のものが渡された場合   2.パラメタidにpageオブジェクトではなく entryオブジェクトのidが渡された場合   3.パラメタidが空の場合   4.パラメタidに現在のblogに属さないentry/ pageのidが渡された場合 考えておかなければならないケース
  72. 72. sub  some_̲action{          my  $app=  shift;          require  MT::Page;          my  $blog  =  app-‐‑‒>blog;          my  $page  =  MT::Page-‐‑‒>load(  $app-‐‑‒>param(  'id'  )  );          if  (!  $page  )  {                  return  $app-‐‑‒>translate(  'Invalid  Page  ID:[_̲1].',  $app-‐‑‒>param(  'id'  )  );          }          my  $perm  =  $app-‐‑‒>user-‐‑‒>is_̲superuser;          if  (!  $perm  )  {                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲administer_̲website                $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲administer_̲blog                                              unless  $perm;                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $blog-‐‑‒>id  )-‐‑‒>can_̲manage_̲pages                  unless  $perm;          }          if  (!  $perm  )  {                  return  $app-‐‑‒>translate(  'Permission  denied.'  );          }          #  この後、$pageへの処理理} mt.cgi?_̲_̲mode=some_̲action&id= <script>alert('do')</script> id=1&blog_̲id=3   ↑   id:1のpageのblog_̲id が3である保証は? idが空だったら?もしくはEntryのIDが渡されたら? てか、テンプレート エンジン使え!
  73. 73. 添削後
  74. 74. sub  some_̲action  {          my  $app  =  shift;          $app-‐‑‒>validate_̲magic(  ʻ‘FooをBarしてもよろしいですか?ʼ’  )  or                  return  $app-‐‑‒>trans_̲error(  'Permission  denied.'  );          require  MT::Page;          my  $page;          if  (!  $app-‐‑‒>param(  'id'  )  ||                  (!  $page  =  MT::Page-‐‑‒>load(  $app-‐‑‒>param(  'id'  )  )  )  {                  return  $app-‐‑‒>trans_̲error(  'Invalid  Page  ID:'[_̲1]'',                                                                MT::Util::encode_̲html(  $app-‐‑‒>param(  'id'  )  )  );          }          if  (  $page-‐‑‒>class  ne  'page'  )  {                  return  $app-‐‑‒>trans_̲error(  'Invalid  Class:'[_̲1]'',  $page-‐‑‒>class  );          }          #  permission  check  case  1          if  (  $app-‐‑‒>blog-‐‑‒>id  !=  $page-‐‑‒>blog_̲id  )  {                  return  $app-‐‑‒>trans_̲error(  'Invalid  BlogID:'[_̲1]'',                                                                MT::Util::encode_̲html(  $app-‐‑‒>blog-‐‑‒>id  )  );          }  #  続く   操作を伴う場合最初にmagic_̲tokenをチェック 渡された値をそのまま表⽰示する場合、エスケープ Entryでないかチェック 違うブログIDに属するもので ないかチェック(※) ※システムスコープやウェブサイトスコープの場合はあり得るケース てか、テンプレート エンジン使え!
  75. 75.        if  (!  $app-‐‑‒>can_̲do(  'manage_̲pages'  )  )  {                  return  $app-‐‑‒>trans_̲error(  'Permission  denied.'  );          }          #  or  case  2          my  $perm  =  $app-‐‑‒>user-‐‑‒>is_̲superuser;            if  (!  $perm  )  {                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $page-‐‑‒>blog_̲id  )-‐‑‒>   can_̲administer_̲website;                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $page-‐‑‒>blog_̲id  )-‐‑‒>   can_̲administer_̲blog  unless  $perm;                  $perm  =  $app-‐‑‒>user-‐‑‒>permissions(  $page-‐‑‒>blog_̲id  )-‐‑‒>   can_̲manage_̲pages  unless  $perm;          }          if  (!  $perm  )  {                  return  $app-‐‑‒>trans_̲error(  'Permission  denied.'  );          }          if  (!  $app-‐‑‒>run_̲callbacks(  'cms_̲save_̲permission_̲filter.page'  $app,  $page  )  {                return  $app-‐‑‒>trans_̲error(  'Permission  denied.'  );          }          #  Do  Something.} $blog-‐‑‒>idではなく$page-‐‑‒>blog_̲idでチェック コールバックをすり 抜けないようにする
  76. 76. ⼀一気に難易易度度あがりましたが...
  77. 77. 結論論
  78. 78. まとめ •セキュアプログラミングは性悪説   •それでも程度度問題。何をやられない ようにするか。何を優先するか(何 は、あきらめるか)   •セキュリティにもUXの視点が必要
  79. 79. まとめ •ユーザーの⼊入⼒力力を信⽤用しない   •エスケープは出⼒力力時に統⼀一する   •SQLを⾃自前で書くな。API使え   •正規ユーザー攻撃型改ざん対策のた めに、⼀一時トークンを使う
  80. 80. ありがとうございました。

×