Line CTF 2021 diveinternal Write Up
2021-03-21 23:29:53

I solved one challenge for web

### (Web) diveinternal [50 pts]

The diveinternal challenge is to get a flag using an ssrf vulenrability.

Above code is code of api, I can see that send a request using a \${target}.

Also, I can know that send a request to internal server because TARGET_HOST is localhost

When I check a docker file, I can know to was open a 5050/5000 port. Viz, I can able use a localhost:5050, localhost:5000.

And first, when I see an important flag reading condition, If environment of server is not Local and exist a file called 'backup/' + dbhash, retrun a flag.

First, I can see that when api server send a request to /coin , put a result value of LanguageNomarize() function to header called Lang and to reponse after bring an information of coin using a getCoinInfo() function.

When I see a LanguateNomarize() function, If to exist a header called Lang, confirm a value of header using regular expression, and I can see to send a request using a request.get() function. In here, Occur an ssrf vulnerability because I can send a request of where I want after modifying a request.host_url and language.

Second, I’ll check the /integrityStatus. We usually can’t send a request because /integrityStatus not communicating to api server. But I can find a value of dbhash by making a request to /integrityStatus using an ssrf vulnerability.

Third, I can see that when I see a /rollback, If value of SignCheck() is true and exist a value of header called Key, call an IntegrityCheck() method.

When I see the IntegrityCheck() method, the value of self.integrityKey and the value of Key are the same, and if the value of self.dbHash and dbHash are not the same, I can see that the RunRollbackDB() function is executed.

RunRollbackDB() is a function that reads and returns a FLAG file if the backup/dbhash file exists, as seen above.

So I thought with the following scenario at first

• Scenario 1
1. Using ssrf vulnerability to send a request to /integrityStatus to get the value of dbHash.
2. Read the FLAG by sending a request to /rollback using the retrieved value of dbHash.
3. FLAG is returned as a header value of lang.

However, an exploit was attempted using the above scenario, but the attack could not be performed because the value of self.dbHash and dbHash in the IntegrityCheck() function had to be different.

So, when I analyzed the code again, I could see that the WriteFile() function was used to create a file under backup/. So, if you create any file using WriteFile function and send the name of the file to dbHash, it is not the same as the value of self.dbHash, which is a variable in the class, and it is Because it exists, it is enough to bypass it and read the flags.

When I see inside the WriteFile() function, a request is sent using the requests.get() function, and the value of url.split('/')[-1] is used as the file name to create it.

The WriteFile() function is called from /download. At this time, if the header value Sign exists, the return value of the SignCheck() function is true, and the src parameter value exists, WriteFile() function is executed.

• Scenario 2
1. Using the ssrf vulnerability, a request was sent to /download to create a random file.
2. Again, using the ssrf vulnerability, sending a request to /rollback to read the FLAG
3. In this case, the self.dbHash != dbHash syntax is bypassed by using the file name.
4. Finally, just read the Lang header.
• A note of caution
1. When creating a file, a request is sent using the requests.get() function, so when creating a file, a URL must be sent to create it.
2. The value of dbHash is parsed once more within the RunRollbackDB() function, and the value of e.isalnum() must be true.
3. When reading the flag, the value of the environment variable ENV should not be local, so port 5000 should be used instead of port 5050.
2021-03-21 23:29:53