32 KiB
GraphQL
âïž HackTricks Cloud âïž -ðŠ Twitter ðŠ - ðïž Twitch ðïž - ð¥ Youtube ð¥
- ãµã€ããŒã»ãã¥ãªãã£äŒç€Ÿã§åããŠããŸããïŒ HackTricksã§äŒç€Ÿã宣äŒãããã§ããïŒãŸãã¯ãPEASSã®ææ°ããŒãžã§ã³ã«ã¢ã¯ã»ã¹ããããHackTricksãPDFã§ããŠã³ããŒããããã§ããïŒSUBSCRIPTION PLANSããã§ãã¯ããŠãã ããïŒ
- The PEASS FamilyãèŠã€ããŠãã ãããç¬å çãªNFTã®ã³ã¬ã¯ã·ã§ã³ã§ãã
- å ¬åŒã®PEASSïŒHackTricksã®ã°ããºãæã«å ¥ããŸãããã
- ð¬ Discordã°ã«ãŒããŸãã¯telegramã°ã«ãŒãã«åå ããããTwitterã§ãã©ããŒããŠãã ããðŠ@carlospolopmã
- ãããã³ã°ã®ããªãã¯ãå ±æããããã«ãPRã hacktricks repo ãš hacktricks-cloud repo ã«æåºããŠãã ããã
ã¯ããã«
GraphQLã¯REST APIã®ä»£æ¿ãšããŠæ©èœããŸããREST APIã§ã¯ãã¯ã©ã€ã¢ã³ãã¯ããã¯ãšã³ãããŒã¿ããŒã¹ããããŒã¿ãã¯ãšãªããããã«è€æ°ã®ãªã¯ãšã¹ããç°ãªããšã³ããã€ã³ãã«éä¿¡ããå¿ èŠããããŸããGraphQLã§ã¯ãããã¯ãšã³ããã¯ãšãªããããã«1ã€ã®ãªã¯ãšã¹ãã®ã¿ãéä¿¡ããå¿ èŠããããŸããããã¯ãè€æ°ã®ãªã¯ãšã¹ããAPIã«éä¿¡ããå¿ èŠããªããããã¯ããã«ã·ã³ãã«ã§ãã
GraphQL
æ°ããæè¡ãç»å Žããã«ã€ããŠãæ°ããè匱æ§ãç»å ŽããŸããããã©ã«ãã§ã¯ãGraphQLã¯èªèšŒãå®è£ ããŠããŸãããããã¯éçºè ãå®è£ ããå¿ èŠãããããšãæå³ããŸããã€ãŸããããã©ã«ãã§ã¯GraphQLã¯èª°ã§ãã¯ãšãªã§ããæ©å¯æ å ±ã¯èªèšŒãããŠããªãæ»æè ã«å©çšå¯èœã§ãã
ãã£ã¬ã¯ããªãã«ãŒããã©ãŒã¹æ»æãå®è¡ããéã«ã¯ã次ã®ãã¹ãè¿œå ããŠGraphQLã€ã³ã¹ã¿ã³ã¹ããã§ãã¯ããŠãã ããã
/graphql
/graphiql
/graphql.php
/graphql/console
/api
/api/graphql
/graphql/api
/graphql/graphql
![](/Mirrors/hacktricks/media/commit/2f907a2cf4ddd126c33d3666d06dd43777e1e7b2/.gitbook/assets/image%20%286%29%20%281%29%20%283%29.png)
ãªãŒãã³ãªGraphQLã€ã³ã¹ã¿ã³ã¹ãèŠã€ããããã©ã®ã¯ãšãªããµããŒãããŠããããç¥ãå¿
èŠããããŸããããã¯ãå
çã·ã¹ãã ã䜿çšããŠè¡ãããšãã§ããŸãã詳现ã«ã€ããŠã¯ããã¡ããåç
§ããŠãã ããïŒGraphQL: A query language for APIs.
Itâs often useful to ask a GraphQL schema for information about what queries it supports. GraphQL allows us to do soâŠ
ãã£ã³ã¬ãŒããªã³ã
ããŒã«graphw00fã¯ããµãŒããŒã§äœ¿çšãããŠããGraphQLãšã³ãžã³ãæ€åºããã»ãã¥ãªãã£ç£æ»äººã«åœ¹ç«ã€æ å ±ã衚瀺ããããšãã§ããŸãã
ãŠãããŒãµã«ã¯ãšãª
GraphQLãšã³ããã€ã³ãã«query{__typename}
ãéä¿¡ãããšãã¬ã¹ãã³ã¹ã®ã©ããã«{"data": {"__typename": "query"}}
ãšããæååãå«ãŸããŸããããã¯ãŠãããŒãµã«ã¯ãšãªãšåŒã°ããURLãGraphQLãµãŒãã¹ã«å¯Ÿå¿ããŠãããã©ããã調æ»ããããã®äŸ¿å©ãªããŒã«ã§ãã
ãã®ã¯ãšãªã¯ããã¹ãŠã®GraphQLãšã³ããã€ã³ãã«ã¯ãã¯ãšãªããããªããžã§ã¯ãã®ã¿ã€ããæååãšããŠè¿ã__typename
ãšããäºçŽæžã¿ãã£ãŒã«ããããããæ©èœããŸãã
åºæ¬çãªåæ
GraphQLã¯éåžžãGETãPOSTïŒx-www-form-urlencodedïŒãPOSTïŒjsonïŒããµããŒãããŠããŸãããã ããã»ãã¥ãªãã£ã®ããã«ã¯CSRFæ»æãé²ãããã«jsonã®ã¿ãèš±å¯ããããšãæšå¥šãããŠããŸãã
å ç
ã¹ããŒãæ
å ±ãçºèŠããããã«å
çã䜿çšããã«ã¯ã__schema
ãã£ãŒã«ããã¯ãšãªããŸãããã®ãã£ãŒã«ãã¯ãã¹ãŠã®ã¯ãšãªã®ã«ãŒãã¿ã€ãã§å©çšå¯èœã§ãã
query={__schema{types{name,fields{name}}}}
ãã®ã¯ãšãªã䜿çšãããšã䜿çšãããŠãããã¹ãŠã®ã¿ã€ãã®ååãèŠã€ããããšãã§ããŸãïŒ
{% code overflow="wrap" %}
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
{% endcode %}
ãã®ã¯ãšãªã䜿çšãããšããã¹ãŠã®ã¿ã€ãããã£ãŒã«ããããã³åŒæ°ïŒããã³åŒæ°ã®ã¿ã€ãïŒãæœåºã§ããŸããããã¯ããŒã¿ããŒã¹ã®ã¯ãšãªæ¹æ³ãç¥ãããã«éåžžã«åœ¹ç«ã¡ãŸãã
ãšã©ãŒ
ãšã©ãŒã衚瀺ããããã©ãããç¥ãããšã¯èå³æ·±ãã§ããããã¯æçšãªæ å ±ãæäŸããŸãã
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
å çãä»ããŠããŒã¿ããŒã¹ã¹ããŒããåæãã
{% hint style="info" %}
å
çãæå¹ã«ãªã£ãŠããå Žåã§ããäžèšã®ã¯ãšãªãå®è¡ãããªãå Žåã¯ãã¯ãšãªæ§é ãã onOperation
ãonFragment
ãããã³ onField
ã®æ瀺ãåé€ããŠã¿ãŠãã ããã
{% endhint %}
#Full introspection query
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation #Often needs to be deleted to run query
onFragment #Often needs to be deleted to run query
onField #Often needs to be deleted to run query
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
ã€ã³ã©ã€ã³ã€ã³ã¹ãã¯ã·ã§ã³ã¯ãšãªãŒïŒ
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
æåŸã®ã³ãŒãè¡ã¯ãGraphQLã®ã¡ã¿æ å ±ïŒãªããžã§ã¯ãåããã©ã¡ãŒã¿ãã¿ã€ããªã©ïŒããã¹ãŠãã³ãããGraphQLã¯ãšãªã§ãã
ããã€ã³ã¹ãã¯ã·ã§ã³ãæå¹ã«ãªã£ãŠããå ŽåãGraphQL Voyagerã䜿çšããŠGUIã§ãã¹ãŠã®ãªãã·ã§ã³ã衚瀺ããããšãã§ããŸãã
ã¯ãšãªã³ã°
ããŒã¿ããŒã¹å ã«ä¿åãããŠããæ å ±ã®çš®é¡ãããã£ãã®ã§ãããã€ãã®å€ãæœåºããŠã¿ãŸãããã
ã€ã³ã¹ãã¯ã·ã§ã³ã§ãçŽæ¥ã¯ãšãªãå®è¡ã§ãããªããžã§ã¯ãïŒååšããã ãã§ã¯ã¯ãšãªã§ããŸããïŒãèŠã€ããããšãã§ããŸãã次ã®ç»åã§ã¯ã"queryType"ã"Query"ãšåŒã°ãã"Query"ãªããžã§ã¯ãã®ãã£ãŒã«ãã®1ã€ã"flags"ã§ãããããããªããžã§ã¯ãã®ã¿ã€ãã§ãããããã£ãŠããã©ã°ãªããžã§ã¯ããã¯ãšãªã§ããŸãã
ã¯ãšãª"flags"ã®ã¿ã€ãã"Flags"ã§ããããšã«æ³šæããŠãã ããããã®ãªããžã§ã¯ãã¯ä»¥äžã®ããã«å®çŸ©ãããŠããŸãïŒ
"Flags"ãªããžã§ã¯ãã¯ååãšå€ã§æ§æãããŠããããšãããããŸãããããã£ãŠã次ã®ã¯ãšãªã§ãã¹ãŠã®ãã©ã°ã®ååãšå€ãååŸã§ããŸãïŒ
query={flags{name, value}}
泚æããŠãã ãããã¯ãšãªãããªããžã§ã¯ãã次ã®äŸã®ããã«æååã®ãããªããªããã£ããªåã§ããå Žåã¯ã次ã®ããã«ã¯ãšãªããããšãã§ããŸãã
query={hiddenFlags}
å¥ã®äŸã§ã¯ã"Query"ã¿ã€ããªããžã§ã¯ãå ã«2ã€ã®ãªããžã§ã¯ããããå ŽåããããŸã: "user"ãš"users"ã ãããã®ãªããžã§ã¯ãã¯æ€çŽ¢ã«åŒæ°ãå¿ èŠãªãå Žåã欲ããããŒã¿ãèŠæ±ããã ãã§ããããããã¹ãŠã®æ å ±ãååŸããããšãã§ããŸãããã®ã€ã³ã¿ãŒãããã®äŸã§ã¯ãä¿åããããŠãŒã¶ãŒåãšãã¹ã¯ãŒããæœåºããããšãã§ããŸãã
ãããããã®äŸã§ã¯ãããè©Šã¿ããšã次ã®ãšã©ãŒã衚瀺ãããŸãã
ã©ããããäœããã®æ¹æ³ã§"uid"ãšããã¿ã€ãã_Int_ã®åŒæ°ã䜿çšããŠæ€çŽ¢ãããããã§ãã
ãšã«ãããç§ãã¡ã¯ãã§ã«ãããç¥ã£ãŠããŸãããåºæ¬çãªåæã®ã»ã¯ã·ã§ã³ã§ã¯ãå¿
èŠãªãã¹ãŠã®æ
å ±ã衚瀺ããã¯ãšãªãææ¡ãããŠããŸãã: query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}
ãã®ã¯ãšãªãå®è¡ãããšãã«æäŸãããç»åãèªããšã"user"ã«ã¯_Int_ã¿ã€ãã®"uid"ãšããargãããããšãããããŸãã
ãããã£ãŠã軜ãuidãã«ãŒããã©ãŒã¹ãå®è¡ãããšã_uid=1_ã§ãŠãŒã¶ãŒåãšãã¹ã¯ãŒããååŸãããããšãããããŸãã:
query={user(uid:1){user,password}}
泚æããŠãã ãããç§ã¯"user"ãš"password"ã®parametersãèŠæ±ã§ããããšãçºèŠããŸããããªããªããååšããªããã®ãæ¢ãããšãããš(query={user(uid:1){noExists}}
)ã次ã®ãšã©ãŒã衚瀺ãããããã§ãã
ãããŠãåæãã§ãŒãºäžã«ã"dbuser"ãªããžã§ã¯ãã«ã¯"user"ãš"password"ãšãããã£ãŒã«ããããããšãããããŸããã
ã¯ãšãªæååã®ãã³ãããªãã¯ïŒ@BinaryShadow_ããã«æè¬ïŒ
ãããquery={theusers(description: ""){username,password}}
ã®ããã«æååã¿ã€ãã§æ€çŽ¢ã§ããå Žåã空ã®æååã§æ€çŽ¢ãããšãã¹ãŠã®ããŒã¿ããã³ããããŸããïŒãã®äŸã¯ãã¥ãŒããªã¢ã«ã®äŸãšã¯é¢ä¿ãããŸããããã®äŸã§ã¯ã"theusers"ãšããååã®Stringãã£ãŒã«ãã®"description"ã䜿çšããŠæ€çŽ¢ã§ãããšä»®å®ããŸããïŒ
GraphQLã¯æ¯èŒçæ°ããæè¡ã§ãããã¹ã¿ãŒãã¢ããã倧äŒæ¥ã®éã§åŸã ã«æ³šç®ãéããŠããŸããããã©ã«ãã§ã¯èªèšŒãäžè¶³ããŠãããããGraphQLãšã³ããã€ã³ãã¯IDORãªã©ã®ä»ã®ãã°ã«ãè匱æ§ããããŸãã
æ€çŽ¢
ãã®äŸã§ã¯ãã¡ãŒã«ã¢ãã¬ã¹ãšååã§èå¥ããã人ç©ãšãååãšè©äŸ¡ã§èå¥ãããæ ç»ã®ããŒã¿ããŒã¹ãæ³åããŠãã ããã人ç©ã¯ä»ã®äººç©ãšåéã«ãªãããšãã§ãã人ç©ã¯æ ç»ãæã€ããšãã§ããŸãã
ååã§äººç©ãæ€çŽ¢ãããã®ã¡ãŒã«ã¢ãã¬ã¹ãååŸããããšãã§ããŸãïŒ
{
searchPerson(name: "John Doe") {
email
}
}
次ã®ããã«ããŠãååã§äººç©ãæ€çŽ¢ãã圌ãã賌èªããŠããæ ç»ãååŸããããšãã§ããŸãïŒ
query {
person(name: "åå") {
subscribedFilms {
title
}
}
}
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
次ã«ã人ç©ã®subscribedMovies
ã®name
ãååŸããæ¹æ³ã瀺ãããŠããããšã«æ³šç®ããŠãã ããã
ãŸããåæã«è€æ°ã®ãªããžã§ã¯ããæ€çŽ¢ããããšãã§ããŸãããã®å Žåã2ã€ã®æ ç»ãæ€çŽ¢ããŸãã
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
ãŸãã¯ããšã€ãªã¢ã¹ã䜿çšããŠè€æ°ã®ç°ãªããªããžã§ã¯ãã®é¢ä¿ãè¡šãããšãã§ããŸã:
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
ãã¥ãŒããŒã·ã§ã³
ãã¥ãŒããŒã·ã§ã³ã¯ããµãŒããŒãµã€ãã§ã®å€æŽãè¡ãããã«äœ¿çšãããŸãã
ã€ã³ã¹ãã¯ã·ã§ã³ã§ã¯ã宣èšããããã¥ãŒããŒã·ã§ã³ãèŠã€ããããšãã§ããŸãã以äžã®ç»åã§ã¯ã"MutationType"ã"Mutation"ãšåŒã°ãã"Mutation"ãªããžã§ã¯ãã«ã¯ãã¥ãŒããŒã·ã§ã³ã®ååïŒãã®å Žåã¯"addPerson"ãªã©ïŒãå«ãŸããŠããŸãã
ãã®äŸã§ã¯ãã¡ãŒã«ãšååã§èå¥ããã人ç©ãšãååãšè©äŸ¡ã§èå¥ãããæ ç»ã®ããŒã¿ããŒã¹ãæ³åããŠãã ããã人ç©ã¯ä»ã®äººç©ãšåéã«ãªãããšãã§ãã人ç©ã¯æ ç»ãæã€ããšãã§ããŸãã
ããŒã¿ããŒã¹å
ã«æ°ããæ ç»ãäœæããããã®ãã¥ãŒããŒã·ã§ã³ã¯ã次ã®ããã«ãªããŸãïŒãã®äŸã§ã¯ãã¥ãŒããŒã·ã§ã³ã¯addMovie
ãšåŒã°ããŠããŸãïŒïŒ
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
泚æããŠãã ãããã¯ãšãªå ã§ã¯ããŒã¿ã®å€ãšåã瀺ãããŠããŸãã
ãŸããmutation ã«ãã£ãŠ persons ã äœæ ããããšããããŸãïŒãã®äŸã§ã¯ addPerson
ãšåŒã°ããŸãïŒãåéããã¡ã€ã«ãæã€äººç©ãäœæããå Žåãåéããã¡ã€ã«ã¯äºåã«ååšããŠããå¿
èŠããããŸãã
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}
1ã€ã®APIãªã¯ãšã¹ãã§ã®ãããã³ã°ãã«ãŒããã©ãŒã¹
ãã®æ
å ±ã¯https://lab.wallarm.com/graphql-batching-attack/ããååŸãããŸããã
ç°ãªãèªèšŒæ
å ±ãæã€å€ãã®ã¯ãšãªãåæã«éä¿¡ããŠèªèšŒããGraphQL APIãããã¯ã¯ã©ã·ãã¯ãªãã«ãŒããã©ãŒã¹æ»æã§ãããGraphQLã®ãããã³ã°æ©èœã«ããã1ã€ã®HTTPãªã¯ãšã¹ãã«è€æ°ã®ãã°ã€ã³/ãã¹ã¯ãŒããã¢ãéä¿¡ããããšãå¯èœã«ãªããŸããããã®ã¢ãããŒãã«ãããå€éšã®ã¬ãŒãç£èŠã¢ããªã±ãŒã·ã§ã³ã¯ãã¹ãŠãæ£åžžã§ããããã¹ã¯ãŒããæšæž¬ããããšãããã«ãŒããã©ãŒã¹ããããååšããªããšæãããããšãã§ããŸãã
以äžã«ãã¢ããªã±ãŒã·ã§ã³ã®èªèšŒãªã¯ãšã¹ãã®æãåçŽãªãã¢ã³ã¹ãã¬ãŒã·ã§ã³ããããŸãã3ã€ã®ç°ãªãã¡ãŒã«/ãã¹ã¯ãŒããã¢ãåæã«éä¿¡ããŠããŸãããã¡ãããåãæ¹æ³ã§1ã€ã®ãªã¯ãšã¹ãã«æ°åãéä¿¡ããããšãå¯èœã§ãã
ã¬ã¹ãã³ã¹ã®ã¹ã¯ãªãŒã³ã·ã§ãããããããããã«ãæåãš3çªç®ã®ãªã¯ãšã¹ãã¯_null_ãè¿ãã_error_ã»ã¯ã·ã§ã³ã«å¯Ÿå¿ããæ å ±ãåæ ããŠããŸãã2çªç®ã®ãã¥ãŒããŒã·ã§ã³ã¯æ£ããèªèšŒããŒã¿ãæã¡ãã¬ã¹ãã³ã¹ã«ã¯æ£ããèªèšŒã»ãã·ã§ã³ããŒã¯ã³ãå«ãŸããŠããŸãã
ã€ã³ããã¹ãã¯ã·ã§ã³ãªãã®GraphQL
GraphQLãšã³ããã€ã³ãã§ã®ã€ã³ããã¹ãã¯ã·ã§ã³ã®ç¡å¹åããŸããŸãå¢ããŠããŸãããã ããäºæããªããªã¯ãšã¹ããåä¿¡ãããå Žåã«GraphQLãã¹ããŒãããšã©ãŒã¯ãclairvoyanceãªã©ã®ããŒã«ã«ãã£ãŠã¹ããŒãã®å€§éšåãåäœæããã®ã«ååã§ãã
ããã«ãBurp Suiteã®æ¡åŒµæ©èœGraphQuailã¯ãBurpãä»ããŠééããGraphQL APIãªã¯ãšã¹ããç£èŠããæ°ããã¯ãšãªããšã«å éšã®GraphQL ã¹ããŒããæ§ç¯ããŸãããŸããGraphiQLãšVoyagerã®ããã«ã¹ããŒããå ¬éããããšãã§ããŸãããã®æ¡åŒµæ©èœã¯ãã€ã³ããã¹ãã¯ã·ã§ã³ã¯ãšãªãåãåã£ãå Žåã«åœã®ã¬ã¹ãã³ã¹ãè¿ããŸãããã®çµæãGraphQuailã¯APIå ã§äœ¿çšã§ãããã¹ãŠã®ã¯ãšãªãåŒæ°ãããã³ãã£ãŒã«ãã衚瀺ããŸãã詳现ã«ã€ããŠã¯ããã¡ããåç §ããŠãã ããã
ããã§GraphQLãšã³ãã£ãã£ãçºèŠããããã®çŽ æŽãããã¯ãŒããªã¹ããèŠã€ãããŸãã
GraphQLã€ã³ããã¹ãã¯ã·ã§ã³é²åŸ¡ã®ãã€ãã¹
ãã¹ãããŠããAPIã§ã€ã³ããã¹ãã¯ã·ã§ã³ã¯ãšãªãå®è¡ã§ããªãå Žåã¯ã__schema
ããŒã¯ãŒãã®åŸã«ç¹æ®æåãæ¿å
¥ããŠã¿ãŠãã ããã
éçºè
ãã€ã³ããã¹ãã¯ã·ã§ã³ãç¡å¹ã«ããå Žåãã¯ãšãªå
ã®__schema
ããŒã¯ãŒããé€å€ããããã«æ£èŠè¡šçŸã䜿çšããããšããããŸããGraphQLã§ã¯ã¹ããŒã¹ãæ¹è¡ãã«ã³ããªã©ã®æåã¯ç¡èŠãããŸãããäžæ£ãªæ£èŠè¡šçŸã§ã¯ç¡èŠãããŸããã
ãããã£ãŠãéçºè
ã__schema{
ã®ã¿ãé€å€ããå Žåã以äžã®ã€ã³ããã¹ãã¯ã·ã§ã³ã¯ãšãªã¯é€å€ãããŸããã
#Introspection query with newline
{
"query": "query{__schema
{queryType{name}}}"
}
ããåäœããªãå Žåã¯ã代æ¿ã®ãªã¯ãšã¹ãã¡ãœããã§ãããŒããå®è¡ããŠã¿ãŠãã ãããã€ã³ãã¹ãã¯ã·ã§ã³ã¯POSTã§ã®ã¿ç¡å¹ã«ãªã£ãŠããå ŽåããããŸããGETãªã¯ãšã¹ãããx-www-form-urlencoded
ãšããã³ã³ãã³ãã¿ã€ããæã€POSTãªã¯ãšã¹ããè©ŠããŠã¿ãŠãã ããã
æŒæŽ©ããGraphQLã®æ§é
ããã€ã³ãã¹ãã¯ã·ã§ã³ãç¡å¹ã«ãªã£ãŠããå Žåã¯ããŠã§ããµã€ãã®ãœãŒã¹ã³ãŒãã確èªããŠã¿ãŠãã ãããã¯ãšãªã¯ãã°ãã°ãã©ãŠã¶ã«äºåã«èªã¿èŸŒãŸããJavaScriptã©ã€ãã©ãªãšããŠä¿åãããŠããŸãããããã®äºåã«æžãããã¯ãšãªã¯ãåãªããžã§ã¯ããé¢æ°ã®ã¹ããŒããšäœ¿çšæ¹æ³ã«é¢ããéèŠãªæ
å ±ãæããã«ããããšããããŸããéçºè
ããŒã«ã®Sources
ã¿ãã§ã¯ãã¯ãšãªãä¿åãããŠãããã¡ã€ã«ãæ€çŽ¢ããããšãã§ããŸããæã«ã¯ç®¡çè
ä¿è·ãããã¯ãšãªãããæ¢ã«å
¬éãããŠããããšããããŸãã
Inspect/Sources/"Search all files"
file:* mutation
file:* query
GraphQLã«ãããCSRF
CSRFãäœãããããªãå Žåã¯ã以äžã®ããŒãžãèªãã§ãã ããïŒ
{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %} csrf-cross-site-request-forgery.md {% endcontent-ref %}
ããã§ã¯ãCSRFããŒã¯ã³ãªãã§æ§æãããããã€ãã®GraphQLãšã³ããã€ã³ããèŠã€ããããšãã§ããŸãã
GraphQLãªã¯ãšã¹ãã¯éåžžãContent-Type **application/json
**ã䜿çšããŠPOSTãªã¯ãšã¹ãã§éä¿¡ãããŸãã
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
ãã ããã»ãšãã©ã®GraphQLãšã³ããã€ã³ãã¯**form-urlencoded
ã®POSTãªã¯ãšã¹ã**ããµããŒãããŠããŸãïŒ
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
ãããã£ãŠãåè¿°ã®ãããªCSRFãªã¯ãšã¹ãã¯ããªãã©ã€ããªã¯ãšã¹ããªãã§éä¿¡ããããããCSRFãæªçšããŠGraphQLã§å€æŽãè¡ãããšãå¯èœã§ãã
ãã ããChromeã®samesite
ãã©ã°ã®æ°ããããã©ã«ãã¯ãããŒå€ã¯Lax
ã§ããããã¯ãã¯ãããŒããµãŒãããŒãã£ã®Webããã®GETãªã¯ãšã¹ãã§ã®ã¿éä¿¡ãããããšãæå³ããŸãã
ãŸããã¯ãšãªãªã¯ãšã¹ããGETãªã¯ãšã¹ããšããŠéä¿¡ããããšãã§ããGETãªã¯ãšã¹ãã§ã¯CSRFããŒã¯ã³ãæ€èšŒãããªãå¯èœæ§ãããããšã«æ³šæããŠãã ããã
ãŸããXS-Search æ»æãæªçšããããšã§ããŠãŒã¶ãŒã®è³æ Œæ å ±ãæªçšããŠGraphQLãšã³ããã€ã³ãããã³ã³ãã³ããå€éšã«æŒæŽ©ãããããšãå¯èœã§ãã
詳现ã«ã€ããŠã¯ããã¡ãã®å ã®æçš¿ãåç §ããŠãã ããã
GraphQLã«ãããèªèšŒ
ãšã³ããã€ã³ãã§å®çŸ©ãããå€ãã®GraphQLé¢æ°ã¯ããªã¯ãšã¹ã¿ãŒã®èªèšŒã®ã¿ããã§ãã¯ããèªå¯ã¯è¡ããŸããã
ã¯ãšãªã®å ¥åå€æ°ãå€æŽããããšã§ãæ©å¯ã®ã¢ã«ãŠã³ã詳现ãæŒæŽ©ããå¯èœæ§ããããŸãã
ãã¥ãŒããŒã·ã§ã³ã¯ãä»ã®ã¢ã«ãŠã³ãããŒã¿ãå€æŽããããšããããšã§ãã¢ã«ãŠã³ãä¹ã£åãã«ã€ãªããå¯èœæ§ãããããŸãã
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
GraphQLã§ã®èªèšŒã®ãã€ãã¹
ã¯ãšãªã®ãã§ãŒã³ã䜿çšãããšã匱ãèªèšŒã·ã¹ãã ããã€ãã¹ã§ããŸãã
以äžã®äŸã§ã¯ãæäœããforgotPasswordãã§ãããããã«é¢é£ããforgotPasswordã¯ãšãªã®ã¿ãå®è¡ãããã¹ãã§ããããšãããããŸããããã¯ãæ«å°Ÿã«ã¯ãšãªãè¿œå ããããšã§ãã€ãã¹ããããšãã§ããŸãããã®å Žåã"register"ãšããã¯ãšãªãšãæ°ãããŠãŒã¶ãŒãšããŠã·ã¹ãã ã«ç»é²ããããã®ãŠãŒã¶ãŒå€æ°ãè¿œå ããŸãã
ãšã€ãªã¢ã¹ã䜿çšããã¬ãŒãå¶éã®ãã€ãã¹
éåžžãGraphQLãªããžã§ã¯ãã«ã¯åãååã®è€æ°ã®ããããã£ãå«ããããšã¯ã§ããŸããããšã€ãªã¢ã¹ã䜿çšãããšãAPIã«è¿ããŠã»ããããããã£ãæ瀺çã«æå®ããããšã§ããã®å¶éããã€ãã¹ã§ããŸãããšã€ãªã¢ã¹ã䜿çšãããšã1ã€ã®ãªã¯ãšã¹ãã§åãã¿ã€ãã®ãªããžã§ã¯ãã®è€æ°ã®ã€ã³ã¹ã¿ã³ã¹ãè¿ãããšãã§ããŸãã
GraphQLã®ãšã€ãªã¢ã¹ã«é¢ãã詳现ã¯ããšã€ãªã¢ã¹ãåç §ããŠãã ããã
ãšã€ãªã¢ã¹ã¯ãå¿ èŠãªAPIåŒã³åºãã®æ°ãå¶éããããã«æå³ãããŠããŸãããGraphQLãšã³ããã€ã³ãããã«ãŒããã©ãŒã¹ããããã«ã䜿çšããããšãã§ããŸãã
å€ãã®ãšã³ããã€ã³ãã§ã¯ããã«ãŒããã©ãŒã¹æ»æãé²ãããã«äœããã®ã¬ãŒãå¶éè£ çœ®ãèšããããŠããŸããäžéšã®ã¬ãŒãå¶éè£ çœ®ã¯ããšã³ããã€ã³ãã§å®è¡ãããæäœã®æ°ã§ã¯ãªããåä¿¡ããHTTPãªã¯ãšã¹ãã®æ°ã«åºã¥ããŠåäœããŸãããšã€ãªã¢ã¹ã¯ãå®è³ªçã«1ã€ã®HTTPã¡ãã»ãŒãžã§è€æ°ã®ã¯ãšãªãéä¿¡ã§ããããã«ããããããã®å¶éããã€ãã¹ã§ããŸãã
以äžã¯ããšã€ãªã¢ã¹ã䜿çšããŠã¹ãã¢ã®å²åŒã³ãŒããæå¹ãã©ããã確èªããäžé£ã®ãšã€ãªã¢ã¹ä»ãã¯ãšãªã®ç°¡ç¥åãããäŸã§ãããã®æäœã¯ã1ã€ã®HTTPãªã¯ãšã¹ãã§è¡ããããããäžåºŠã«èšå€§ãªæ°ã®å²åŒã³ãŒãããã§ãã¯ããããšãã§ããå¯èœæ§ããããã¬ãŒãå¶éããã€ãã¹ããããšãã§ããŸãã
#Request with aliased queries
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
ããŒã«
è匱æ§ã¹ãã£ããŒ
- https://github.com/gsmith257-cyber/GraphCrawler: ã¹ããŒããååŸããæ©å¯ããŒã¿ãæ€çŽ¢ããèªèšŒããã¹ãããã¹ããŒãããã«ãŒããã©ãŒã¹æ»æããæå®ãããã¿ã€ããžã®ãã¹ãèŠã€ããããã«äœ¿çšã§ããããŒã«ãããã§ãã
- https://blog.doyensec.com/2020/03/26/graphql-scanner.html: ã¹ã¿ã³ãã¢ãã³ãŸãã¯Burpæ¡åŒµãšããŠäœ¿çšã§ããŸãã
- https://github.com/swisskyrepo/GraphQLmap: CLIã¯ã©ã€ã¢ã³ããšããŠã䜿çšã§ããæ»æãèªååããããã«ã䜿çšã§ããŸãã
- https://gitlab.com/dee-see/graphql-path-enum: GraphQLã¹ããŒãã§æå®ãããã¿ã€ãã«å°éããããŸããŸãªæ¹æ³ããªã¹ãããããŒã«ã§ãã
- https://github.com/doyensec/inql: é«åºŠãªGraphQLãã¹ãã®ããã®Burpæ¡åŒµæ©èœã§ããInQL v5.0ã®ã³ã¢ã§ãã_Scannerã§ã¯ãGraphQLãšã³ããã€ã³ããŸãã¯ããŒã«ã«ã®å éšã¹ããŒããã¡ã€ã«ãåæã§ããŸãããã¹ãŠã®å¯èœãªã¯ãšãªãšãã¥ãŒããŒã·ã§ã³ãèªåçæããåæã®ããã«æ§é åããããã¥ãŒã«æŽçããŸããAttacker_ã³ã³ããŒãã³ãã§ã¯ããããGraphQLæ»æãå®è¡ã§ããŸããããã¯ãå®è£ ãäžååãªã¬ãŒãå¶éãåé¿ããããã«åœ¹ç«ã¡ãŸãã
ã¯ã©ã€ã¢ã³ã
- https://github.com/graphql/graphiql: GUIã¯ã©ã€ã¢ã³ã
- https://altair.sirmuel.design/: GUIã¯ã©ã€ã¢ã³ã
èªåãã¹ã
{% embed url="https://graphql-dashboard.herokuapp.com/" %}
- AutoGraphQLã®èª¬æãããª: https://www.youtube.com/watch?v=JJmufWfVvyU
åèæç®
- https://jondow.eu/practical-graphql-attack-vectors/
- https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696
- https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4
- http://ghostlulz.com/api-hacking-graphql/
- https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md
- https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696
- https://portswigger.net/web-security/graphql
âïž HackTricks Cloud âïž -ðŠ Twitter ðŠ - ðïž Twitch ðïž - ð¥ Youtube ð¥
- **ãµã€ããŒã»ãã¥ãªãã£äŒæ¥ã§åããŠããŸããïŒ HackTricksã§ããªãã®äŒç€Ÿã宣äŒãããã§ããïŒãŸãã¯ãPEASSã®ææ°ããŒãžã§ã³ã«ã¢ã¯ã»ã¹ããããHackTricksãPDFã§ããŠã³ããŒãããããããã§ããïŒSUBSCRIPTION PLANSããã§ãã¯ããŠãã ããïŒ
- The PEASS FamilyãçºèŠããŸããããç§ãã¡ã®ç¬å çãªNFTã®ã³ã¬ã¯ã·ã§ã³
- å ¬åŒã®PEASSïŒHackTricksã®ã¹ã¯ãã°ãæã«å ¥ããŸããã
- ð¬ Discordã°ã«ãŒããŸãã¯telegramã°ã«ãŒãã«åå ããããTwitter ðŠ@carlospolopmããã©ããŒããŠãã ããã
- ãããã³ã°ã®ããªãã¯ãå ±æããã«ã¯ãhacktricks repo ãš hacktricks-cloud repo ã«PRãæåºããŠãã ããã