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

GraphQL API を悪意あるクエリから守る手法

GraphQL API を悪意あるクエリから守る手法

GraphQL では容易にサーバーに負荷をかけるクエリを書けてしまいます。この発表では、そうした悪意あるクエリから GraphQL API を守る手法を紹介します。

本発表の内容は以下のブログ記事でも詳しく解説しています。
https://yigarashi.hatenablog.com/entry/graphql-query-analysis

Yuu Igarashi

May 14, 2020
Tweet

More Decks by Yuu Igarashi

Other Decks in Programming

Transcript

  1. ϖύϘɾ͸ͯͳٕज़େձ
    ZJHBSBTIJ
    (SBQI2-"1*Λ
    ѱҙ͋ΔΫΤϦ͔ΒकΔख๏

    View Slide

  2. (SBQI2-

    View Slide

  3. ಋೖ(SBQI2-
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ

    View Slide

  4. ಋೖ(SBQI2-
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View Slide

  5. ಋೖ(SBQI2-
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ

    View Slide

  6. ಋೖ(SBQI2-
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ
    {
    "me": {
    "name": "yigarashi",
    "interests": [
    "ϓϩδΣΫτϚωδϝϯτ",
    "GraphQL",
    "ϓϩάϥϛϯάݴޠཧ࿦",
    ]
    }
    }
    ฦΓ஋ʢ+40/ʣ

    View Slide

  7. ಋೖ(SBQI2-
    "1*ͷͨΊͷΫΤϦݴޠͱΫΤϦʹԠͨ͡σʔλΛฦ͢ϥϯλΠϜ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    me {
    name
    interests
    }
    }
    ΫΤϦ
    {
    "me": {
    "name": "yigarashi",
    "interests": [
    "ϓϩδΣΫτϚωδϝϯτ",
    "GraphQL",
    "ϓϩάϥϛϯάݴޠཧ࿦",
    ]
    }
    }
    ฦΓ஋ʢ+40/ʣ
    ΫΤϦͱಉ͡ܗͷ
    +40/͕ฦ͞ΕΔ

    View Slide

  8. ಋೖ(SBQI2-
    ΋͏গ͠ෳࡶͳྫ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View Slide

  9. ಋೖ(SBQI2-
    ΋͏গ͠ෳࡶͳྫ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 1) {
    name
    cities(first: 2) {
    name
    }
    }
    }
    ΫΤϦ

    View Slide

  10. ಋೖ(SBQI2-
    ΋͏গ͠ෳࡶͳྫ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 1) {
    name
    cities(first: 2) {
    name
    }
    }
    }
    ΫΤϦ
    Ҿ਺Λड͚औΔ͜ͱ͕Ͱ͖Δɻ
    pSTU͸42-Ͱݴ͏MJNJU

    View Slide

  11. ಋೖ(SBQI2-
    ΋͏গ͠ෳࡶͳྫ
    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 1) {
    name
    cities(first: 2) {
    name
    }
    }
    }
    ΫΤϦ
    {
    "countries": [
    {
    "name": "೔ຊ",
    "cities": [
    { "name": "ژ౎ࢢ" },
    { "name": "৽॓۠" },
    ]
    },
    ]
    }
    ฦΓ஋ʢ+40/ʣ
    Ҿ਺Λड͚औΔ͜ͱ͕Ͱ͖Δɻ
    pSTU͸42-Ͱݴ͏MJNJU

    View Slide

  12. ύϫϑϧ

    View Slide

  13. ѱҙ͋Δਓ͕
    ࢖͏ͱʜʜ

    View Slide

  14. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View Slide

  15. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    name
    cities(first: 100) {
    name
    streets(first: 1000) {
    name
    }
    }
    }
    }
    ΫΤϦ

    View Slide

  16. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    name
    cities(first: 100) {
    name
    streets(first: 1000) {
    name
    }
    }
    }
    }
    ΫΤϦ

    View Slide

  17. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    name
    cities(first: 100) {
    name
    streets(first: 1000) {
    name
    }
    }
    }
    }
    ΫΤϦ
    ºº
    ສϊʔυ

    View Slide

  18. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    name
    cities(first: 100) {
    name
    streets(first: 1000) {
    name
    }
    }
    }
    }
    ΫΤϦ
    ºº
    ສϊʔυ

    View Slide

  19. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ

    View Slide

  20. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ΫΤϦ

    View Slide

  21. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ΫΤϦ

    View Slide

  22. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ΫΤϦ
    ඇৗʹॏ͍ܭࢉΛ
    ճ

    View Slide

  23. ѱҙ͋ΔΫΤϦ

    ΫϥΠΞϯτ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ΫΤϦ
    ඇৗʹॏ͍ܭࢉΛ
    ճ

    View Slide

  24. ࠓ೔ͷςʔϚ
    (SBQI2-"1*Λѱҙ͋ΔΫΤϦʢʹҙਤతʹෛՙΛ͔͚ΔΫΤϦʣ͔ΒकΔ

    View Slide

  25. ࠓ೔ͷςʔϚ
    (SBQI2-"1*Λѱҙ͋ΔΫΤϦʢʹҙਤతʹෛՙΛ͔͚ΔΫΤϦʣ͔ΒकΔ
    యܕతͳෛՙʢσʔλͷऔಘݩ͸3%#ͱԾఆ͢Δʣ
    σʔλྔ
    ܭࢉྔ
    جຊతͳΞΠσΟΞ
    ʮΫΤϦΛ੩తղੳͯ͠ෛՙͷ໰୊͕ͳ͍͜ͱΛ֬ೝ࣮ͯ͠ߦ͢Δʯ

    View Slide

  26. ۩ମతͳख๏
    ϗϫΠτϦετʹΑΔ੍ݶ
    DPNQMFYJUZʹΑΔ੍ݶ

    View Slide

  27. ۩ମతͳख๏
    ϗϫΠτϦετʹΑΔ੍ݶ
    DPNQMFYJUZʹΑΔ੍ݶ

    View Slide

  28. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    ΫϥΠΞϯτ

    View Slide

  29. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ

    View Slide

  30. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ
    {
    countries(first: 10) {
    name
    }
    }

    View Slide

  31. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ
    {
    countries(first: 10) {
    name
    }
    }

    View Slide

  32. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ

    View Slide

  33. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ
    {
    countries(first: 10) {
    name
    population
    }
    }

    View Slide

  34. ϗϫΠτϦετʹΑΔ੍ݶ
    αʔόʔ͕ड͚෇͚ΔΫΤϦΛϗϫΠτϦετͱ͓ͯ࣋ͬͯ͘͠ɻϦΫΤετ͞
    ΕͨΫΤϦ͕ϗϫΠτϦετʹҰக͢Δ৔߹͚࣮ͩߦ͢Δ
    αʔόʔ
    ʢϥϯλΠϜʣ
    {
    countries(first: 10) {
    name
    }
    }
    ϗϫΠτϦετ
    ʜ ʜ
    ΫϥΠΞϯτ
    {
    countries(first: 10) {
    name
    population
    }
    }

    View Slide

  35. ϗϫΠτϦετʹΑΔ੍ݶ
    ϝϦοτ
    ಋೖ͕༰қʢΫΤϦ͕จࣈྻͱͯ͠Ұக͢Δ͔֬ೝ͢Δ͚ͩͰྑ͍ʣ
    ޮՌ͕ߴ͍ʢຊ౰ʹ࢖͏ΫΤϦͷΈϗϫΠτϦετͱͯ͠ڐՄ͢ΔͨΊʣ
    σϝϦοτ
    ϗϫΠτϦετͷϝϯςφϯείετ
    ެ։"1*΍εςʔΫϗϧμʔͷҧ͏ΫϥΠΞϯτͰ͸࢖͍ͮΒ͍
    ૯ධ
    ؔ܎͢Δ։ൃऀɾΫϥΠΞϯτ͕গͳ͍৔߹ʹ͔ͳΓ༗ޮ

    View Slide

  36. ۩ମతͳख๏
    ϗϫΠτϦετʹΑΔ੍ݶ
    DPNQMFYJUZʹΑΔ੍ݶ

    View Slide

  37. ۩ମతͳख๏
    ϗϫΠτϦετʹΑΔ੍ݶ
    DPNQMFYJUZʹΑΔ੍ݶ

    View Slide

  38. DPNQMFYJUZʹΑΔ੍ݶ
    ΫΤϦͷෛՙʹൺྫͯ͠େ͖͘ͳΔ਺஋ʢDPNQMFYJUZʣΛܭࢉ͢Δɻͦͷ਺
    ஋͕ᮢ஋Λ௒͑ͨ৔߹͸࣮ߦ͠ͳ͍

    View Slide

  39. DPNQMFYJUZʹΑΔ੍ݶ
    ΫΤϦͷෛՙʹൺྫͯ͠େ͖͘ͳΔ਺஋ʢDPNQMFYJUZʣΛܭࢉ͢Δɻͦͷ਺
    ஋͕ᮢ஋Λ௒͑ͨ৔߹͸࣮ߦ͠ͳ͍
    యܕతͳෛՙʹ͍ͭͯDPNQMFYJUZͷྫΛݟ͍ͯ͘
    σʔλྔ
    ܭࢉྔ
    %#ΞΫηεճ਺
    ʢ஫ҙʣDPNQMFYJUZͷܭࢉํ๏͸ແ਺ʹߟ͑ΒΕΔɻࠓ೔ࣔ͢ͷ͸Ұྫ

    View Slide

  40. ྫϊʔυ਺ʹൺྫ͢ΔDPNQMFYJUZ

    View Slide

  41. ྫϊʔυ਺ʹൺྫ͢ΔDPNQMFYJUZ
    {
    countries(first: 50) {
    name
    cities(first: 100) {
    name
    }
    }
    }

    View Slide

  42. ྫϊʔυ਺ʹൺྫ͢ΔDPNQMFYJUZ
    ϊʔυ਺DPVOUSJFTºDJUJFT
    OPEFT
    {
    countries(first: 50) {
    name
    cities(first: 100) {
    name
    }
    }
    }

    View Slide

  43. ྫϊʔυ਺ʹൺྫ͢ΔDPNQMFYJUZ
    ϊʔυ਺DPVOUSJFTºDJUJFT
    OPEFT
    ͜Ε͕ᮢ஋ҎԼͳΒ࣮ߦ͢Δ
    {
    countries(first: 50) {
    name
    cities(first: 100) {
    name
    }
    }
    }

    View Slide

  44. ྫϊʔυ਺ʹൺྫ͢ΔDPNQMFYJUZ
    ϊʔυ਺DPVOUSJFTºDJUJFT
    OPEFT
    ͜Ε͕ᮢ஋ҎԼͳΒ࣮ߦ͢Δ
    {
    countries(first: 50) {
    name
    cities(first: 100) {
    name
    }
    }
    }
    ࢀߟ(JU)VC(SBQI2-"1*Wͷ/PEFMJNJU
    ϊʔυ਺͸ ·Ͱ
    ϦετͷऔಘͰ͸Ҿ਺ʹpSTU͔MBTU͕ඞਢͰҎ಺

    View Slide

  45. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ

    View Slide

  46. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ
    type City {
    name
    superComplexStatistics @cost(n: 10)
    }

    View Slide

  47. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ
    type City {
    name
    superComplexStatistics @cost(n: 10)
    }
    (SBQI2-ͷEJSFDUJWFΛར༻ͯ͠ɺ
    ܕఆٛʢεΩʔϚʣͷଆͰॏ͍ܭࢉʹίετΛ͚ͭΔɻ
    αʔόʔ͸͜ͷ৘ใΛࢀরͯ͠DPNQMFYJUZΛܭࢉ͢Δ

    View Slide

  48. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ
    type City {
    name
    superComplexStatistics @cost(n: 10)
    }
    (SBQI2-ͷEJSFDUJWFΛར༻ͯ͠ɺ
    ܕఆٛʢεΩʔϚʣͷଆͰॏ͍ܭࢉʹίετΛ͚ͭΔɻ
    αʔόʔ͸͜ͷ৘ใΛࢀরͯ͠DPNQMFYJUZΛܭࢉ͢Δ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ΫΤϦ

    View Slide

  49. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ
    type City {
    name
    superComplexStatistics @cost(n: 10)
    }
    (SBQI2-ͷEJSFDUJWFΛར༻ͯ͠ɺ
    ܕఆٛʢεΩʔϚʣͷଆͰॏ͍ܭࢉʹίετΛ͚ͭΔɻ
    αʔόʔ͸͜ͷ৘ใΛࢀরͯ͠DPNQMFYJUZΛܭࢉ͢Δ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ܭࢉίετ ºDJUJFT
    ºDPTU

    ΫΤϦ

    View Slide

  50. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ
    type City {
    name
    superComplexStatistics @cost(n: 10)
    }
    (SBQI2-ͷEJSFDUJWFΛར༻ͯ͠ɺ
    ܕఆٛʢεΩʔϚʣͷଆͰॏ͍ܭࢉʹίετΛ͚ͭΔɻ
    αʔόʔ͸͜ͷ৘ใΛࢀরͯ͠DPNQMFYJUZΛܭࢉ͢Δ
    {
    countries(first: 100) {
    cities(first: 100) {
    superComplexStatistics
    }
    }
    }
    ܭࢉίετ ºDJUJFT
    ºDPTU

    ΫΤϦ
    %#ΞΫηεճ਺΋શ͘ಉ͡ΞΠσΟΞͰDPNQMFYJUZΛઃܭͰ͖Δɻ%#ΞΫ
    ηε͕ൃੜ͢ΔϑΟʔϧυʹDPTUΛ͚ͭΕ͹ɺ%#ΞΫηεճ਺ʹൺྫͯ͠
    DPNQMFYJUZ͕૿Ճ͢ΔΑ͏ʹͰ͖Δɻ

    View Slide

  51. ࣮૷
    (SBQI2-Ͱྑ͘࢖ΘΕΔݴޠͰ͸ϥΠϒϥϦ౳ͷαϙʔτ͕͋Δ
    +BWB4DSJQUHSBQIRMDPTUBOBMZTJTͳͲ
    (PHRMHFO͕αϙʔτ͍ͯ͠Δ
    αϙʔτͷͳ͍ݴޠͰͲ͏͢Δ͔
    ΫΤϦղੳ͚ͩϚΠΫϩαʔϏεͱͯ͠੾Γग़ͯ͠ผݴޠΛ࢖͏
    ࣗલͰ࣮૷͢Δ

    View Slide

  52. ମݧஊ
    ͱ͋ΔαʔϏεͰϑϧεΫϥονͰΫΤϦղੳΛ࣮૷ʢ1FSMͩͬͨͷͰʜʣ
    εςʔΫϗϧμʔͷҧ͏ΫϥΠΞϯτ͕༧૝͞ΕͨͷͰϗϫΠτϦετʹΑΔ
    ੍ݶ͸ݟૹͬͨ
    QBSTFͱFYFDVUFͷؒʹDPNQMFYJUZʹΑΔ੍ݶΛ࢓ࠐΜͩ
    ϕʔε͸ϊʔυ਺ʹΑΔ੍ݶ
    શ݅औಘ͢ΔϑΟʔϧυ΍%#ΞΫηε͕ൃੜ͢ΔϑΟʔϧυʹߴΊͷίε
    τΛ͚ͭΔ
    ᮢ஋͸௨ৗར༻Λ્֐͠ͳ͍େ͖Ίͷ஋ʹઃఆ
    ؀ڥม਺Ͱᮢ஋ΛઃఆͰ͖ΔΑ͏ʹͯ͠ૉૣ͘ରॲՄೳʹ

    View Slide

  53. ݱঢ়ͷ՝୊
    DPNQMFYJUZͷϕετϓϥΫςΟεཱ͕֬͞Ε͍ͯͳ͍
    ࠓճ͸ϊʔυ਺ɾܭࢉίετɾ%#ΞΫηεʹண໨ͯٞ͠࿦Λ͕ͨ͠ɺͦ΋
    ͦ΋͜͜·Ͱ౿ΈࠐΜͰٞ࿦͍ͯ͠Δࢿྉ͕গͳ͍
    ޙΖʹ%#Ҏ֎͕͍ΔέʔεͳͲଞʹ΋࿦఺͸͋Γͦ͏
    ੈͷதͷϥΠϒϥϦ͸DPNQMFYJUZ͕ͻͱͭͷέʔεΛް͘αϙʔτ͍ͯ͠Δ
    ϊʔυ਺ɾܭࢉίετͱ͍ͬͨෳ਺ͷई౓Λѻ͍ͮΒ͍
    ࢓ํͳ͘ͻͱͭͷDPNQMFYJUZʹෳ਺ͷई౓Λԡ͠ࠐΉ͜ͱ΋
    +BWB4DSJQUͷHSBQIRMDPTUBOBMZTJTͰ͸࣮ݱՄೳͳ͜ͱΛ֬ೝ

    View Slide

  54. ·ͱΊ
    (SBQI2-Ͱ͸ҙਤతʹෛՙΛ͔͚ΔΫΤϦΛ༰қʹهड़Ͱ͖Δ
    ͭͷ๷ӴखஈΛ঺հͨ͠
    ϗϫΠτϦετʹΑΔ੍ݶ
    DPNQMFYJUZʹΑΔ੍ݶ
    ׬ᘳͳ๷Ӵ͸ඞͣ͠΋ඞཁͳ͍
    ϦεΫͱରࡦͷશମ૾Λݟ౉͠ཁ݅ʹ͋ͬͨίεύͷྑ͍ํ਑ΛऔΔ
    ϒϩάهࣄ൛ʮ(SBQI2-"1*Λѱҙ͋ΔΫΤϦ͔ΒकΔख๏ʯ
    IUUQTZJHBSBTIJIBUFOBCMPHDPNFOUSZHSBQIRMRVFSZBOBMZTJT

    View Slide