๐ Introduction
GraphQL์ ์น์์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ด๊ฒ ๊ฐ์ ธ๋ ๊ฒ์ ๋ชฉ์ ์ผ๋ก ํ๋ Query Lanauge๋ก ๊ธฐ์กด REST API์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ๋ฑ์ฅํ ๊ธฐ์ ์ ๋๋ค. REST API๊ฐ ์๋ฒ์์ ์ ์ํ ์คํ์ ๋ฐ๋ผ ํธ์ถํด์ ๋ฐ์ดํฐ๋ฅผ ์ป๋ ํํ๋ผ๋ฉด GraphQL์ ํด๋ผ์ด์ธํธ๊ฐ ์ ์ํ ํฌ๋งท์ผ๋ก ๊ฐ์ ธ์ค๊ณ ์ถ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ธฐ์ ์ ๋๋ค.
REST API, SQL์ ํตํ ์๋น์ค๋ค์ด ๋ฐฑ์๋์์ ์ฟผ๋ฆฌํ๊ณ ์ฒ๋ฆฌํ๋ค๋ฉด, GraphQL ์๋น์ค๋ ํ๋ก ํธ์์ ์ฟผ๋ฆฌํ๊ณ ์ฒ๋ฆฌํ๋ ๋น์ค์ด ๋์ต๋๋ค. ๊ทธ๋์ GraphQL์ HTTP ์์ฒญ์ ๊ตฌ์กฐ๋ฅผ ์ ์ํ๋ Schema์ ์ค์ ์ฟผ๋ฆฌ์ธ Query์ Mutation ๋ถ๋ถ์ผ๋ก ๋๋์ด์ง๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ GQL์ด๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
Schema
type Query {
polygon (sides: Int, regular: Boolean): Polygon
}
type Polygon {
perimeter: Float
area: Float
}
Query & Mutation
query {
polygon(sides: 1, regular: true) {
perimeter
area
}
}
mutation {
createPerson(input: { ... }) {
person {
id
name
}
}
updatePerson(input: { ... }) {
person {
id
name
}
}
}
๐ก Offensive techniques
How to Testing
GraphQL์ ์ฌ์ฉํ๋ ์๋น์ค๋ ๋ณดํต ์์ฃผ ์ฌ์ฉ๋๋ Form, JSON ๊ธฐ๋ฐ์ด ์๋ ๋ณ๋์ Body๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณดํต /graphql ๋ฑ์ ๊ฒฝ๋ก๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ฉฐ ํด๋น ๊ฒฝ๋ก๊ฐ ์๋๋๋ผ๋ query๋ฅผ ํฌํจํ ๊ฒฝ์ฐ GrphQL ์๋น์ค๋ก ํ์ธํฉ๋๋ค.
Testing point
์์์ ์ค๋ช ํ๋ฏ์ด GraphQL์์์ ๋ฐฑ์๋๋ ์ ๋ฌ๋ฐ์ GQL์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌ๋ง ํฉ๋๋ค. ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ๋ถ๋ถ์ ํ๋ก ํธ์์ ๋ด๋นํ๊ฒ ๋ฉ๋๋ค. ๊ทธ ์๋ฆฌ๋ ๊ฒฐ๊ตญ ๊ธฐ์กด ๋ฐฑ์๋์ ๊ฐ์ถฐ์ง ๋ก์ง๋ค์ด ํ๋ก ํธ์๋๋ก ๋ง์ด ๋์ด์จ๋ค๋ ์๋ฏธ์ด๊ณ , ๊ณง ์ฐ๋ฆฌ๊ฐ ํ ์คํ ํ ํฌ์ธํธ๊ฐ ๋์ด๋ฌ๋ค๋ ์๋ฏธ๊ฐ ๋๊ธฐ๋ ํฉ๋๋ค.
ZAP
ZAP์ GQL์ ์ง์ํฉ๋๋ค. Request์์ Schema์ Query ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๊ณ , Site tree์์๋ GQL ๋ด์ฉ์ ๋ฐ๋ผ ์ผ๋ถ ํ๊ธฐ๊ฐ ๋ฉ๋๋ค. ๋ํ GQL์ ๊ฐ๊ฐ ํ๋๋ค์ ๋ชจ๋ Input Vectors์ ํฌํจ๋๊ธฐ ๋๋ฌธ์ ActiveScan ์ GQL๋ ํ ์คํ ๋ฒกํฐ๊ฐ ์ถ๊ฐ๋์ด ์ค์บ๋ฉ๋๋ค.
GraphQL ์ฒ๋ฆฌ์ ๋ํ ์ค์ ์ Options
> GraphQL
์ ์กด์ฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋จ Import
> Import a GraphQL ~~~
๋ฉ๋ด๋ฅผ ํตํด File์ด๋ URL ๊ธฐ๋ฐ์ผ๋ก GraphQL Scheme์ ๋ก๋ํ ์๋ ์์ต๋๋ค.
BurpSuite
BurpSuite ๋ํ GQL์ ์ง์ํฉ๋๋ค. BurpSuite๋ Request ํญ์์ ๋ณ๋๋ก GraphQL ํญ์ ์ง์ํ๋ฉฐ, Schema์ Query๋ฅผ ๋๋ ์ ๋ณผ ์ ์์ต๋๋ค.
๋ค๋ง GQL ์ง์์ ์ํด์ GraphQL Raider๋ ํ์ฅ ๊ธฐ๋ฅ ์ค์น๊ฐ ํ์ํฉ๋๋ค.
Insomnia
Insomnia๋ API ํ ์คํ ๋๊ตฌ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ฐ๋ฐ์๊ฐ ๋ง์ด ์ฌ์ฉํ๋ฉฐ, Postman๊ณผ ๊ฐ์ด API ์คํ์ ์ ์ํ๊ณ ๋ง์ถฐ์ ํ ์คํธํ ์ ์๋ ๋๊ตฌ์ ๋๋ค. ์ฌ๊ธฐ์๋ GraphQL์ ์ง์ํ๊ธฐ ๋๋ฌธ์ GQL ์ ๋ณด๋ฅผ ๋ก๋ํ์ฌ ์ค์๊ฐ์ผ๋ก ํ ์คํธํ ์ ์์ต๋๋ค.
๊ฐ์ธ์ ์ผ๋ก๋ ๊ฐ๋ฐ/๋ณด์ํ ์คํ ์ ์ ๋ง ์ ์ฌ์ฉํ๊ณ ์๊ณ ์ข์ํ๋ ๋๊ตฌ์์. Insomnia๊ฐ ๊ถ๊ธํ์๋ค๋ฉด โInsomnia๋ก REST API๋ฅผ ์ฝ๊ฒ ํ ์คํธํ์ ๐โ ๊ธ์ ์ฝ์ด์ฃผ์ธ์!
Attacks
GraphQL Injection
โCullinan > GraphQL Injectionโ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.
IDOR
API, REST API ์๋น์ค์ ๋์ผํ๊ฒ GraphQL ๋ํ IDOR์ ์ํฅ์ ๋ง์ด ๋ฐ์ต๋๋ค.
Original
query {
getMyInfo(userid: "31114") {
key
secret
}
}
Attack
query {
getMyInfo(userid: "0") { # 0 is admin user id
key
secret
}
}
IDOR์ ๋ํ ์์ธํ ๋ด์ฉ์ Cullinan > IDOR ํญ๋ชฉ์ ์ฐธ๊ณ ํด์ฃผ์ธ์!
Improper Access Control
GrphQL์ GraphQL์ ์ฒ๋ฆฌํ๋ ์๋ฒ๊ฐ ์ฌ๋ฌ API๋ฅผ ํธ๋ค๋งํ๊ณ ์์ต๋๋ค. ๋ง์น API G/W์ ์ ์ฌํ ํํ์ธ๋ฐ์, ์ด๋ฌํ ๊ฒฝ์ฐ ๊ฐ API์ ๊ถํ ๋ฒ์๋ ์ธ์ฆ ๋ฑ์ ๋์น๊ธฐ ์ฝ์ต๋๋ค. GraphQL์ ์ฐ๋๋๋ ์๋น์ค๋ GQL์ ๋ฐ๋ผ ์ถฉ๋ถํ API๋ฅผ ์ํํ ์ ์๊ณ ์ธ๋ถ๋ก ์คํ์ ์ง์ ์ ์ผ๋ก ๋ ธ์ถ์ํค์ง ์์๋ GQL์ ํตํด ๊ตฌ์กฐ๋ฅผ ํ์ ํ๊ณ ํธ์ถ๋ ์ ์์ต๋๋ค.
query {
getAdminData() {
key
secret
}
}
Race condition
API ๊ณํต์ ์๋น์ค๋ค์ด ์ฝ๋๋ฅผ ์์ฑํ ํํ์ ๋ฐ๋ผ์ Race condition์ ์ํฅ์ ๋ฐ๋ ๊ฒ ์ฒ๋ผ GraphQL ๋ํ ๋จ์๊ฐ์ ๋ง์ ์์ ์์ฒญ์ด ์์ ๋ ๋ฐฑ์๋์ ์ฒ๋ฆฌ ๋ก์ง์ ๋ฐ๋ผ Race condition์ ์ํฅ์ ๋ฐ์ ์ ์์ต๋๋ค. ๋ํ Query๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์์ ๋กญ๊ฒ ๋์ง ์ ์๊ธฐ ๋๋ฌธ์ ์ฟผ๋ฆฌ๋ฅผ ์ ๊ตฌ์ฑํ์ฌ Race condition์ ์ฑ๊ณตํ ํ๋ฅ ์ ๋์ผ ์๋ ์์ต๋๋ค.
Etc
์ด์ธ์๋ ์ฌ๋ฌ Injection ์ด๋ ์น ์ทจ์ฝ์ ๋ฑ์ด ๋ชจ๋ ์ ํจํ ์ ์์ต๋๋ค. ์ ๋ฐ์ ์ผ๋ก Schema๋ Query ๋ํด์ ํ ์คํธ๊ฐ ํ์ํฉ๋๋ค.
๐ก Defensive techniques
Basic
๊ธฐ๋ณธ์ ์ผ๋ก ์์ ์ด์ผ๊ธฐํ ๊ณต๊ฒฉ ๋ฐฉ๋ฒ์ ๋ํ ๋์๋ค์ ๋ชจ๋ ์ด๋ฃจ์ด์ ธ์ผ ํฉ๋๋ค. GraphQL์ด ์ฐ๊ฒฐ๋๋ API ๋ค์ ๋ชจ๋ ํน์๋ฌธ์ ๊ฒ์ฆ ๋ฑ์ผ๋ก Injection ๊ณต๊ฒฉ์ ์๋ฐฉํ๊ณ ๋ถํ์ํ ์ ๋ณด๋ Client๋ก ๋๊ฒจ์ฃผ์ง ์๋๋ก ์๋ฌ ์ฒ๋ฆฌ ๋ฑ์ด ์ ๋์ด ์์ด์ผ ํฉ๋๋ค.
Access Control
GraphQL์ ํธ์์ฑ์ผ๋ก ์๋ ๊ฒ ์ค ํ๋๊ฐ ๋ฐ๋ก ์ธ์ฆ/์ธ๊ฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ฐ๊ฐ ๊ฐ๋ณ ๊ธฐ๋ฅ๋ค์ด ํ๋์ GQL๋ก ๋ฌถ์ด๊ธฐ ๋๋ฌธ์ ์ ๊ฒฝ์จ์ ๊ถํ์ ์ ๋ถ๋ฆฌํ๊ณ ๊ถํ์ ๋ง๋ ์์ฒญ์ธ์ง ๊ตฌ๋ณํ๋ ๋ก์ง๋ค์ด ํ์ํฉ๋๋ค.
Large Query ๋์
GQL์ ํด๋ผ์ด์ธํธ์์ ์์ฒญํ๊ธฐ ๋๋ฌธ์ ๋๋๋ก ์ ์์ ์ธ ์ฟผ๋ฆฌ๊ฐ ์ ์ก๋ ์ ์์ต๋๋ค. ์ด์ ๋ํด์ Timeout์ด๋ Maximum Query Depth ๋ฑ์ผ๋ก ํฐ ์์ฒญ์ ๋ํด ์ ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์๋ ๊ธ์ ์ฐธ๊ณ ํด์ฃผ์ธ์.
https://www.howtographql.com/advanced/4-security/
๐น Tools
- GraphQLmap
- GraphQL-voyager
- GraphQL Security Toolkit
- Graphql-path-enum
- GraphQL IDE
- ClairvoyanceX
- InQL
- Insomnia
- AutoGraphql + introspection