かってぃのブログ

喫茶店を遊牧しながら勉強したり開発したりする大学院生のブログです。

katty0324

PHPの標準関数で画像加工したらあんまり良くなかったので、ImageMagickの勉強をしようと思います。できるだけ品質を落とさずに縮小とか、画質調整とかできると良いけれど。

on 2011-06-19 18:06:35

webから

GDライブラリは汚かった。

以前、PHPから簡単に使えるという理由でGDライブラリを使ってみました。

PHPで簡単に画像を縮小させるライブラリを作りました

http://choilog.com/katty0324/blog/35

ですが、画質が劣化してしまって残念だったので、今回はImageMagickを試してみようと思い立った次第です。

さくらインターネットのレンタルサーバに導入

とのことなので、php.iniにextension=imagick.soを書き足して、phpinfo()してみると確かに認識されました。簡単でよろしい。

サンプルコード

試しに画像を縮小してみます。

<?php
$image = new Imagick('photo1.jpg');
$image->thumbnailImage(200, 0);

header("Content-type: image/jpeg");
echo $image;

こんなソースで、写真の横幅を200pxになるように縮小します。

画質比較

元の画像


GDライブラリ(左)とImageMagick(右)の比較

結論

確かに綺麗!

(そもそも画像の容量が違うので、その辺りの問題なのかもしれません。)

by katty0324 on 2011-06-19 19:26:39

コメント(0)

katty0324

クロスサイトスクリプティング脆弱性対策。(1)<>"&は文字参照に(2)Javascriptに動的に文字列を渡す時はURLエンコード(3)hrefやsrcの値がスクリプトでないか確認(4)session.cookie_httponly=on(5)TraceEnable

on 2011-04-14 15:38:35

webから

クロスサイトスクリプティングとは?

クロスサイトスクリプティング(略してXSS)は、WEBサイト中で動的にHTMLやJavascriptを生成している部分に、悪意のあるコードを埋め込む攻撃です。

昨年、TwitterがXSS脆弱性によって、大騒ぎになった日がありました。

こんな風に、WEBサイトに怪しげなソースコードを埋め込み、それを見た別のユーザーに悪影響を与えます。

この対策は本質的な対策法は、

悪意あるコードを埋め込めないようにする

これに尽きます。

1. <>"&は文字参照にする

HTML中に悪意あるコードを埋め込めなくするためには、特殊な意味合いをもつ<>"&の文字をエスケープする必要があります。

$str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');

こうすると、<は&lt;に、>は&gt;に、&は&amp;に、"は&quote;に、'は&#39;に変換されます。

このように文字参照に変換してしまえば、悪意あるコードを無力化できます。

第2引数は、ENT_QUOTESが一番強くエスケープしてくれるので、特に理由がなければこれを使うのが良いでしょう。

2. Javascriptに動的に文字列を渡す時はURLエンコードする

HTMLに悪意あるコードを埋め込まれるのは、まだ被害が少ないですが、Javascriptを埋め込まれると大きな被害に繋がります。

そこで可能な限りJavascriptを動的に生成することはしたくないのですが、どうしてもそうする必要が出てくる場所があります。

たとえば、Javascriptでエラーメッセージを表示させるが、そのエラーメッセージはPHPで動的に作りたい場合などです。

<?php
$error = 'エラーです。';
?>
<script type="text/javascript">
    alert('<?php echo $error?>');

    // alert('エラーです。');
</script>

こうしておくと、$errorに怪しげなコードが埋め込まれた時に、それがJavascriptとして実行されてしまう危険があります。(この例のように、$errorに任意の文字列が埋め込まれる心配がない場合は危険はありませんが)

function EscapeJavascriptString($s) {
    return preg_replace_callback('/[^-\.0-9a-zA-Z]+/u',
    function ($matches) {
        $u16 = mb_convert_encoding($matches[0], 'UTF-16');
        return preg_replace('/[0-9a-f]{4}/', '\u$0', bin2hex($u16));
    }
    , $s);
}

そこで、このような文字列をエスケープする関数を利用します。

alert('<?php echo EscapeJavascriptString($error);?>');
// alert('\u30a8\u30e9\u30fc\u3067\u3059\u3002');

これで、Javascriptとして実行されるようなコードが埋め込まれても、エスケープされるので危険性がなくなります。

3. hrefやsrcの値がURLか確認する

Javascriptはscriptタグの中だけでなく、aタグのhref属性や、imgタグのsrc属性の中でも実行することができます。

<a href="javascript: alert('js!');">js</a>

だから、aタグのhref属性などにjavascriptが埋め込まれていないかを確認する必要があります。これは、1.で紹介したhtmlspecialcharsを使っても取り除けないので注意です。

function isUrl($url) {
    return (boolean)preg_match('/\A(https?:\/\/|\/)/',$url);
}

このような正規表現などを使って、本当にURLが指定されているかを事前に確認します。

4. php.iniでsession.cookie_httponly=on

ここからは保険的な対策です。

JavascriptからCookieにアクセスできると、XSS脆弱性によってCookieに保存されたセッションID等が漏えいする恐れがあります。

php.iniでsession.cookie_httponlyをonにしておくと、Javascript経由でCookieにアクセスすることができなくなります。cookie_httponlyの設定で不都合が生じなければ設定した方が良いでしょう。

レンタルサーバなどで直接php.iniが触れない場合は、実行時に次のようにini_setで設定することもできます。

ini_set('session.cookie_httponly',1);

5. httpd.confでTraceEnable Off

これも保険的な対策ですが、XSS対策に漏れがあった場合に、クロスサイトトレーシング(XST)という攻撃を受ける恐れがあります。

これは、HTTPのTRACEメソッドを使うことでパスワード等を盗む攻撃で、Apacheの設定でこのメソッドを使えないようにしておいた方が安全です。

参考文献

体系的に学ぶ 安全なWebアプリケーションの作り方」を参考に書きました。非常に分かりやすくて良い本です。

by katty0324 on 2011-04-15 14:48:34

コメント(0)

katty0324

PHPで配列同士の足し算できたんだ!今まで無駄なことしてた。 $array1=array('User'=>'katty'); $array2=array('Profile'=>'22 years old'); $array3=$array1+$array2; #pg_

on 2011-02-21 00:29:34

webから

PHPでは+演算子で配列の足し算ができる!

PHPは便利で、配列の足し算ができます!

たとえばこんな風に、ユーザー情報の配列とログイン情報の配列があって、これらをまとめてひとつの配列にしたい時に使うことができます。

$user = array(
    'name'=>'katty',
    'background'=>'black',
    'url'=>'http://choilog.com/'
);
$login = array(
    'id'=>'12345',
    'password'=>'abcde'
);
print_r($user + $login);

結果は次のようになります。

Array
(
    [name] => katty
    [background] => black
    [url] => http://choilog.com/
    [id] => 12345
    [password] => abcde
)

使っているのは、ただの+演算子です。簡単です。

array_mergeでも配列の足し算ができる

+演算子でなく、array_mergeという関数を使っても、配列の足し算ができます。

array_merge($user,$login)

この場合は、結果は全く同じになります。

+演算子とarray_mergeの違い

  • +演算子は、上書きをしない
  • array_mergeは、上書きをする

というのが大きな違いだと思います。

$default = array(
    'phptype'=>'mysql',
    'username'=>'root',
    'password'=>'',
    'hostspec'=>'localhost',
    'database'=>'choilog'
);
$config = array(
    'password'=>'abcde',
    'options'=>'charset=utf8'
);
print_r($default + $config);
print_r(array_merge($default, $config));

このように$defaultという設定配列に$configという配列を組み合わせて、データベース設定を作るような場合を考えます。

+演算子の場合($default + $config)

+演算子の場合、passwordの要素は演算子の左の配列に最初からありましたので、上書きされません。optionsの要素は左の配列になかったので、追加されます。

Array
(
    [phptype] => mysql
    [username] => root
    [password] =>
    [hostspec] => localhost
    [database] => choilog
    [options] => charset=utf8
)

array_mergeの場合(array_merge($default, $config))

array_mergeの場合、passwordの要素は第1引数の配列に最初からありますが、上書きされます。optionsの要素も、追加されます。

Array
(
    [phptype] => mysql
    [username] => root
    [password] => abcde
    [hostspec] => localhost
    [database] => choilog
    [options] => charset=utf8
)

by katty0324 on 2011-04-11 16:00:07

コメント(0)