More Related Content
Similar to MTで学ぶセキュアプログラミング@MT Tokyo
Similar to MTで学ぶセキュアプログラミング@MT Tokyo(20)
MTで学ぶセキュアプログラミング@MT Tokyo
- 24. 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で評価する
- 26. 主なもの
•XSS = Cross Site Scripting
•CSRF = Cross site request
forgeries
•SQL (OS Command) Injection
•Directory traversal
- 31. 例例 : 検索索結果テンプレート
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;!
- 32. 例例 : 検索索結果テンプレート
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;!
コード中でエスケープしてる
- 34. 例例 : 検索索結果テンプレート
...!
!
sub context_script {!
my ( $ctx, $args, $cond ) = @_;!
!
my $search_string!
= decode_html($ctx->stash('search_string')
package MT::Template::Context::Search;!
わざわざ戻してんのかよ!
- 47. my $app = MT->instance;!
my $q = $app->param(‘search’);!
my @entries = MT-
>model(‘entry’)!
->load( {!
title => { like => $q }, !
} )
例例 : Perlによる実装
- 49. var q = jQuery('#search').value;!
var params = {!
search: q,!
searchFields: "title,body",!
};!
api.listEntries(siteId, params,
function(response) {!
if (response.error) {!
return;!
}!
例例 : JavaScriptによる実装
- 59. 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以外を返すと権限エラー
- 76. 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!
}
ちゃんと権限をチェック
+更更新が必要なものは権限をチェック
- 78. 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への処理理}
- 80. 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が渡されたら?
てか、テンプレート
エンジン使え!
- 82. 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に属するもので
ないかチェック(※)
※システムスコープやウェブサイトスコープの場合はあり得るケース
てか、テンプレート
エンジン使え!
- 83. 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でチェック
コールバックをすり
抜けないようにする