Upgrade to Pro — share decks privately, control downloads, hide ads and more …

os.makedirsの細かすぎるセキュリティの話

C5b4d57a23b991d41ac0a89926ab4f8a?s=47 Ryuji Tsutsui
February 10, 2021
25

 os.makedirsの細かすぎるセキュリティの話

C5b4d57a23b991d41ac0a89926ab4f8a?s=128

Ryuji Tsutsui

February 10, 2021
Tweet

Transcript

  1. os.makedirsͷ ࡉ͔͗͢ΔηΩϡϦςΟͷ࿩ Ryuji Tsutsui ΈΜͳͷPythonษڧձ#66 ࠙਌ձLT

  2. ࣗݾ঺հ • Ryuji Tsutsui@ryu22e • ࿡ຊ໦ͷϑΟϯςοΫܥاۀͰDjangoΛ࢖ͬͯWebαʔϏεΛ࡞͍ͬͯ·͢ • ৭ʑͳOSSίϛϡχςΟʹؔΘ͍ͬͯ·͢ • Python

    Boot CampίΞελοϑ • Shonan.pyελοϑ • Python Charity Talks in Japanελοϑ • झຯ: өըؑ৆ɾ֨ಆٕ؍ઓ ݄೔ʢ౔ʣ։࠵ ࢀՃͯ͠Ͷʂ
  3. ࠓ೔࿩͢͜ͱ • Python 3.7Ҏ্ͷos.makedirs
 ʢෳ਺֊૚ͷσΟϨΫτϦΛ࡞੒͢Δؔ਺ʣʹՃΘͬͨʮ͋Δมߋʯ ʹ͍ͭͯͷ࿩ • ͲΜͳมߋͳͷ͔ • ͳͥมߋ͞Εͨͷ͔

    • ͜ͷมߋʹΑΓى͜Γ͏Δ੬ऑੑ
  4. ͲΜͳมߋͳͷ͔

  5. ެࣜυΩϡϝϯτΛಡΜͰΈΑ͏ • https://docs.python.org/3.7/library/os.html#os.makedirs ΑΓҾ༻ Changed in version 3.7: The mode

    argument no longer affects the file permission bits of newly-created intermediate-level directories. όʔδϣϯ3.7ͷมߋ: modeҾ਺͸ɺ৽͘͠࡞੒͞ΕͨதؒϨϕϧͷσΟϨΫ τϦͷϑΝΠϧύʔϛογϣϯϏοτʹӨڹΛ༩͑ͳ͘ͳΓ·ͨ͠ɻ ↓࿨༁
  6. ࣮ࡍʹίʔυΛॻ͍ͯݕূͯ͠ΈΑ͏ """example.py"""
 import os from pathlib import Path # dir1΋dir2΋ύʔϛογϣϯ700Λࢦఆͨͭ͠΋Γ

    mode = 0o700 os.makedirs(Path.cwd() / "dir1" / "dir2", mode=mode)
  7. Python 3.6Ͱͷ࣮ߦ݁Ռ $ python3.6 example.py $ stat --format='%a' dir1 dir1/dir2/

    700 700
  8. Python 3.7Ҏ্Ͱͷ࣮ߦ݁Ռ $ umask 077 && python3.7 example.py $ stat

    --format='%a' dir1 dir1/dir2/ 700 700 $ umask 022 && python3.7 example.py $ stat --format='%a' dir1 dir1/dir2/ 755 700 $ umask 000 && python3.7 example.py $ stat --format='%a' dir1 dir1/dir2/ 777 700 $ umask 000 && python3.6 example.py $ stat --format='%a' dir1 dir1/dir2/ 700 700 EJSʢதؒϨϕϧͷσΟϨΫτϦʣͷ ύʔϛογϣϯ͸NPEFҾ਺ͷӨڹΛड͚ͣɺ VNBTLͷ஋ʹΑͬͯ݁Ռ͕มΘΔ
 ʢPdVNBTLʣ 1ZUIPOͩͱVNBTLͷӨڹ͸ड͚ͳ͍
  9. ͳͥมߋ͞Εͨͷ͔

  10. CPythonͷιʔείʔυ͔Βgit blameͰḷͬͯ Έͨ • ʮos.makedirs('dir1/dir2', 0) always failsʯͱ͍͏Issue͕ڍ͕͍ͬͯ ͨ •

    https://bugs.python.org/issue19930
  11. • 3.6Ͱʮos.makedirs('dir1/dir2', 0)ʯΛ࣮ߦ͢Δͱʮdir1ʯͷύʔϛο γϣϯ͕0ʹͳΓɺʮdir2ʯ͕࡞੒Ͱ͖ͳ͍ɻ
 ʢ਌σΟϨΫτϦͷύʔϛογϣϯʹॻ͖ࠐΈݖݶ͕ͳ͍ͷͰʣ • mkdirίϚϯυͰ͸ɺʮmkdir -p -m 0

    dir1/dir2ʯͩͱdir1͸ ʮ0o777&~umaskʯͷύʔϛογϣϯ͕༩͑ΒΕΔɻ͜Εͱಉ͡࢓༷ ʹͨ͠΄͏͕͍͍ͷͰ͸ʁ • ٞ࿦ͷ݁Ռɺ͜ͷఏҊ͕ड͚ೖΕΒΕΔ͜ͱʹͳͬͨ ཁ໿͢Δͱ͜͏
  12. ͜ͷมߋʹΑΓى͜Γ͏Δ੬ऑੑ

  13. ͜ͷมߋ͕ݪҼͷDjango੬ऑੑ͕࣮ࡍʹ͋ͬͨ • CVE-2020-24583ɾCVE-2020-24584 
 ʢ2020೥9݄1೔ʹमਖ਼൛ϦϦʔεʣ • ੩తϑΝΠϧΛஔ͘σΟϨΫτϦɾΩϟογϡͷॻ͖ࠐΈઌσΟϨ ΫτϦΛ࡞੒͢Δࡍʹos.makedirsΛmode෇͖Ͱ࢖͍ͬͯΔ • umaskͷ஋ʹΑͬͯ͸ɺ͜ΕΒͷσΟϨΫτϦʹ༨෼ͳύʔϛο

    γϣϯΛ༩͑ͯ͠·͏Մೳੑ͕͋ͬͨ
  14. ͜ͷΑ͏ʹରԠ͞Εͨ import os from pathlib import Path mode = 0o700

    # modeʹࢦఆͨ͠஋ͱಉ͡ύʔϛογϣϯʹͳΔΑ͏Ұ୴umaskΛมߋ old_umask = os.umask(0o777 & ~mode) try: os.makedirs(Path.cwd() / "dir1" / "dir2", mode=mode) finally: # σΟϨΫτϦ࡞੒ޙʹumaskΛݩʹ໭͢ os.umask(old_umask)
  15. ·ͱΊ • Python 3.7͔Βos.makedirsͷmodeҾ਺͸ʮதؒϨϕϧͷσΟϨΫτ ϦʯʹӨڹΛ༩͑ͣɺumaskͷ஋ʹΑͬͯύʔϛογϣϯ͕ܾ·Δ • mkdirίϚϯυͷ࢓༷ʹ߹Θͤͯ͜͏ͳͬͨ • 3.6·Ͱͱಉ͡ڍಈΛظ଴͢ΔίʔυΛॻ͘ͱɺσΟϨΫτϦʹ༨෼ ͳύʔϛογϣϯΛ༩͑ͯ͠·͏Մೳੑ͕͋ΔͷͰ஫ҙ

    • ճආ͢Δʹ͸os.makedirsͷલޙͰos.umaskΛݺͿ͜ͱ