Slide 1

Slide 1 text

஌ΒΕ͟ΔSerialize @PHP Study Cybozu Inc, Yuichi Sugiyama

Slide 2

Slide 2 text

Who am I • ਿࢁ ༞Ұ @oogFranz • αΠϘ΢ζ5೥໨ΤϯδχΞ • େاۀ޲͚άϧʔϓ΢ΣΞ Λ࡞ͬͯΔʢPHP 7.2) • ෳۀδϟζϛϡʔδγϟϯ@MASHݭָஂ

Slide 3

Slide 3 text

serialize(), unserialize()࢖ͬͯ·͔͢ʁ

Slide 4

Slide 4 text

serialize() όϦϕϯϦ $a = ["hoge", 3, true]; $a[] = &$a; echo serialize($a); # a:4:{i:0;s:4:"hoge";i:1;i:3;i:2;b:1;i:3;a:4: {i:0;s:4:"hoge";i:1;i:3;i:2;b:1;i:3;R:5;}} • PHPͷ஋Λ෮ݩՄೳͳจࣈྻʹม׵͢Δɻ • ΫϥεͷΠϯελϯεͰ͋ͬͯ΋ม׵Մೳʂ • DBʹ΋อଘͰ͖Δʂ΍ͬͨͶʂ

Slide 5

Slide 5 text

serialize() όϦϕϯϦ $a = ["hoge", 3, true]; $a[] = &$a; echo serialize($a); # a:4:{i:0;s:4:"hoge";i:1;i:3;i:2;b:1;i:3;a:4: {i:0;s:4:"hoge";i:1;i:3;i:2;b:1;i:3;R:5;}} • PHPͷ஋Λ෮ݩՄೳͳจࣈྻʹม׵͢Δɻ • ΫϥεͷΠϯελϯεͰ͋ͬͯ΋ม׵Մೳʂ • DBʹ΋อଘͰ͖Δʂ΍ͬͨͶʂ

Slide 6

Slide 6 text

Կ͕໰୊ʁ • serialize() ʹ͸࣮͸ͦΜͳʹ໰୊͸ͳ͍ • ٯؔ਺ͷunserialize()ʹ͍͔ͭ͘ͷ੬ऑੑ͕͋Δ

Slide 7

Slide 7 text

PHP Object Injection ʢPOIʣ • ҎԼͷ৚͕݅ຬͨ͞Ε͍ͯΔ৔߹ɺ։ൃऀ͕ҙਤ͍ͯ͠ͳ͍
 ίʔυΛ߈ܸऀ͕࣮ߦͰ͖Δɻ • __wakeup(), __destruct()ͳͲͷϚδοΫϝιουʹ
 ෭࡞༻ͷ͋Δίʔυ͕ॻ͔Ε͍ͯΔ • unserialize()ͷҾ਺ʹϢʔβʔ͔Βͷೖྗ͕౉͞ΕΔ

Slide 8

Slide 8 text

ϚδοΫϝιου • ಛఆͷ৚݅ͰࣗಈͰൃಈ͢Δຐ๏ • serialize()ͷ࣮ߦ࣌ʹϚδοΫϝιουͷ __sleep() ͕
 ͋ͬͨΒࣗಈͰ࣮ߦ͞ΕΔ • unserialize()࣌ʹɺϚδοΫϝιουͷ __wakeup() ͕
 ͋ͬͨΒࣗಈͰ࣮ߦ͞ΕΔ

Slide 9

Slide 9 text

αϯϓϧ class POIExample{ private $filename; public function __destruct() { unlink($this->filename); } } unserialize('O:10:"POIExample":1:{s: 20:"POIExamplefilename";s:8:"test.php";}')

Slide 10

Slide 10 text

αϯϓϧ class POIExample{ private $filename; public function __destruct() { unlink($this->filename); } } unserialize('O:10:"POIExample":1:{s: 20:"POIExamplefilename";s:8:"test.php";}') ߈ܸऀ͕೚ҙͷϑΝΠϧͷ࡟আ͕Մೳʂ

Slide 11

Slide 11 text

POIͷ͕͜͜ා͍ • ࣮ࡍʹunserializeʹ౉͞ΕΔ͜ͱ͕ͳ͍ΫϥεͰ͋ͬͯ΋ɺ
 auto_loadͷ࢓૊Έ͕͋Δͱ࣮ߦ͞Εͯ͠·͏ɻ • privateͷϝϯόม਺ʹ΋೚ҙͷ஋Λ୅ೖՄೳ
 setterΛհ͞ͳ͍ͷͰɺߟྀ͕೉͍͠ɻ • ԾʹsetterͰσΟϨΫτϦτϥόʔαϧΛ๷͍Ͱ͍ͯ΋ແҙຯ

Slide 12

Slide 12 text

• json_encode(), json_decode()Λ࢖͏ɻ
 ˠΦϒδΣΫτΛγϦΞϥΠζɾσγϦΞϥΠζ͢ΔͷͰͳ͚Ε͹ े෼ɻ • allowed_classesΦϓγϣϯΛ࢖͏
 ˠࢦఆ͞ΕͨΫϥεͷΦϒδΣΫτʹ͔͠
 ɹม׵͞Εͳ͍͜ͱ͕อূ͞ΕΔ POIΛ๷͙ʹ͸ʁ

Slide 13

Slide 13 text

allowed_classes Φϓγϣϯ $serialized_str = 'O:10:"POIExample":1:{s:20:"POIExamplefilename";s: 8:"test.php";}'; $result = unserialize($serialized_str, ['allowed_classes' => false]); var_dump($result); /* object(__PHP_Incomplete_Class)#2 (2) { ["__PHP_Incomplete_Class_Name"]=> string(10) "POIExample" ["filename":"POIExample":private]=> string(8) "test.php" } */ echo serialize($result); // O:10:"POIExample":1:{s:20:"POIExamplefilename";s:8:"test.php";}

Slide 14

Slide 14 text

allowed_classesͰकΕΔ΋ͷ • ڐՄ͞Ε͍ͯͳ͍ΫϥεΛunserialize()͢Δͱɺ__PHP_Incomplete_Class ʹม׵͞ΕΔ • ͦͷΦϒδΣΫτΛ΋͏Ұ౓serialize͢Δͱ
 ʢͳ͔ͥʣݩʹ໭Δɻ • σϑΥϧτ஋͸ true (ΨόΨό)ͳͷͰ໌ࣔతʹࢦఆ͢Δඞཁ͕͋Δ • falseΛࢦఆ͢Ε͹ɺ͋ΒΏΔΫϥεΛڋઈ͢Δ

Slide 15

Slide 15 text

__PHP_Incomplete_ClassʹͳͬͨΒΤϥʔʹ͍ͨ͠ • ةͳ͍΋ͷ͕౉͖͍ͬͯͯΔͷͰΤϥʔʹ͍ͨ͠ • get_class Λͯ͠ɺ__PHP_Incomplete_Class ͔Λௐ΂Δ • unserialize_callback_func ͸ݺͼग़͞Εͳ͍ͷͰ஫ҙɻ

Slide 16

Slide 16 text

allowed_classes͕͋Ε͹unserialize࢖ͬ ͯ΋ྑ͍ʁ https://twitter.com/nikita_ppv/status/895571304325062656

Slide 17

Slide 17 text

allowed_classes͕͋Ε͹unserialize࢖ͬ ͯ΋ྑ͍ʁ https://www.php.net/manual/ja/function.unserialize.php

Slide 18

Slide 18 text

unserializeͷ੬ऑੑ͸੬ऑੑͱΈͳ͞Εͳ͍ • ϝϞϦपΓͳͲͷෆ۩߹Ͱ͋ͬͯ΋੬ऑੑͱΈͳ͞Εͳ͍
 Մೳੑ͕͋Δ • ΧδϡΞϧʹϝϞϦपΓͷෆ۩߹͕ใࠂ͞Ε͍ͯΔ

Slide 19

Slide 19 text

serializeͨ͠஋ΛDBʹೖΕΔ͜ͱʹ͍ͭͯ • SQL Ξϯνύλʔϯͷ
 5ষ EAVʢΤϯςΟςΟɾΞτϦϏϡʔτɾόϦϡʔʣ
 ʹͳͬͯΔՄೳੑ͕ߴ͍ɻ

Slide 20

Slide 20 text

MySQLͱserialize • MySQLͷtextʹγϦΞϥΠζσʔλΛೖΕ͍ͯΔ৔߹ɺ
 จࣈ਺͕Φʔόʔ͢Δͱɺ్தͰ੾ΒΕͯ͠·͍ɺ
 ෮ݩͰ͖ͳ͘ͳΔɻʢStrict SQL Modeʹґଘʣ • MySQL 5.7͔Β͸JSONܕ͕࢖͑ΔΑ͏ʹͳͬͨͷͰɺ
 ಈతεΩʔϚ͕Ͳ͏ͯ͠΋ඞཁͳ৔߹΋JSONܕΛߟ͑ͨํ͕ Αͦ͞͏ɻ

Slide 21

Slide 21 text

·ͱΊ • serialize(), unserialize()Λ࢖͍ͬͯͳ͍ͷͳΒɺͦΕ͕Ұ൪ • ΋͠࢖͍ͬͯΔͷͳΒɺPOIΛ๷͙ͨΊɺϢʔβʔೖྗσʔλ͕ೖͬͯ͜ͳ͍͜ͳ͍͜ͱΛ͔֬Ί Α͏ • ՄೳͰ͋Ε͹json_encode, json_decodeʹஔ͖͔͑Α͏ • ͦΕ΋ແཧͳΒɺallowed_classesΦϓγϣϯͰPOI͸͠ͷ͝͏ • DBʹ͸อଘ͠ͳ͍Α͏ʹ͠·͠ΐ͏ • ϝϞϦपΓͷෆ۩߹΋͋ΔͷͰஔ͖׵͑Λݕ౼͠·͠ΐ͏ɻ