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

5ef13e6d95d73c58a4641bf20083c245?s=128

Yuu Igarashi

May 14, 2020
Tweet

Transcript

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

  2. (SBQI2-

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

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

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

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

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

    } } ΫΤϦ { "me": { "name": "yigarashi", "interests": [ "ϓϩδΣΫτϚωδϝϯτ", "GraphQL", "ϓϩάϥϛϯάݴޠཧ࿦", ] } } ฦΓ஋ʢ+40/ʣ ΫΤϦͱಉ͡ܗͷ +40/͕ฦ͞ΕΔ
  8. ಋೖ(SBQI2- ΋͏গ͠ෳࡶͳྫ ΫϥΠΞϯτ αʔόʔ ʢϥϯλΠϜʣ

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

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

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

    cities(first: 2) { name } } } ΫΤϦ { "countries": [ { "name": "೔ຊ", "cities": [ { "name": "ژ౎ࢢ" }, { "name": "৽॓۠" }, ] }, ] } ฦΓ஋ʢ+40/ʣ Ҿ਺Λड͚औΔ͜ͱ͕Ͱ͖Δɻ pSTU͸42-Ͱݴ͏MJNJU
  12. ύϫϑϧ

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

  14. ѱҙ͋ΔΫΤϦ  ΫϥΠΞϯτ αʔόʔ ʢϥϯλΠϜʣ

  15. ѱҙ͋ΔΫΤϦ  ΫϥΠΞϯτ αʔόʔ ʢϥϯλΠϜʣ { countries(first: 100) { name

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

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

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

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

  20. ѱҙ͋ΔΫΤϦ  ΫϥΠΞϯτ αʔόʔ ʢϥϯλΠϜʣ { countries(first: 100) { cities(first:

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

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

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

    100) { superComplexStatistics } } } ΫΤϦ ඇৗʹॏ͍ܭࢉΛ ճ
  24. ࠓ೔ͷςʔϚ (SBQI2-"1*Λѱҙ͋ΔΫΤϦʢʹҙਤతʹෛՙΛ͔͚ΔΫΤϦʣ͔ΒकΔ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    cities(first: 100) { name } } } ࢀߟ(JU)VC(SBQI2-"1*Wͷ/PEFMJNJU ϊʔυ਺͸ ·Ͱ ϦετͷऔಘͰ͸Ҿ਺ʹpSTU͔MBTU͕ඞਢͰҎ಺
  45. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ

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

  47. ྫܭࢉίετʹൺྫ͢ΔDPNQMFYJUZ type City { name superComplexStatistics @cost(n: 10) } (SBQI2-ͷEJSFDUJWFΛར༻ͯ͠ɺ

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

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

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

    ܕఆٛʢεΩʔϚʣͷଆͰॏ͍ܭࢉʹίετΛ͚ͭΔɻ αʔόʔ͸͜ͷ৘ใΛࢀরͯ͠DPNQMFYJUZΛܭࢉ͢Δ { countries(first: 100) { cities(first: 100) { superComplexStatistics } } } ܭࢉίετ ºDJUJFT ºDPTU   ΫΤϦ %#ΞΫηεճ਺΋શ͘ಉ͡ΞΠσΟΞͰDPNQMFYJUZΛઃܭͰ͖Δɻ%#ΞΫ ηε͕ൃੜ͢ΔϑΟʔϧυʹDPTUΛ͚ͭΕ͹ɺ%#ΞΫηεճ਺ʹൺྫͯ͠ DPNQMFYJUZ͕૿Ճ͢ΔΑ͏ʹͰ͖Δɻ
  51. ࣮૷ (SBQI2-Ͱྑ͘࢖ΘΕΔݴޠͰ͸ϥΠϒϥϦ౳ͷαϙʔτ͕͋Δ +BWB4DSJQUHSBQIRMDPTUBOBMZTJTͳͲ (PHRMHFO͕αϙʔτ͍ͯ͠Δ αϙʔτͷͳ͍ݴޠͰͲ͏͢Δ͔ ΫΤϦղੳ͚ͩϚΠΫϩαʔϏεͱͯ͠੾Γग़ͯ͠ผݴޠΛ࢖͏ ࣗલͰ࣮૷͢Δ

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

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

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