aszx87410 / ctf-writeups

ctf writeups

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DiceCTF 2021 - Missing Flavortext

aszx87410 opened this issue · comments

commented

It'a simple login page:

source code:

const crypto = require('crypto');
const db = require('better-sqlite3')('db.sqlite3')

// remake the `users` table
db.exec(`DROP TABLE IF EXISTS users;`);
db.exec(`CREATE TABLE users(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT,
  password TEXT
);`);

// add an admin user with a random password
db.exec(`INSERT INTO users (username, password) VALUES (
  'admin',
  '${crypto.randomBytes(16).toString('hex')}'
)`);

const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// parse json and serve static files
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('static'));

// login route
app.post('/login', (req, res) => {
  if (!req.body.username || !req.body.password) {
    return res.redirect('/');
  }

  if ([req.body.username, req.body.password].some(v => v.includes('\''))) {
    return res.redirect('/');
  }

  // see if user is in database
  const query = `SELECT id FROM users WHERE
    username = '${req.body.username}' AND
    password = '${req.body.password}'
  `;

  let id;
  try { id = db.prepare(query).get()?.id } catch {
    return res.redirect('/');
  }

  // correct login
  if (id) return res.sendFile('flag.html', { root: __dirname });

  // incorrect login
  return res.redirect('/');
});

app.listen(3000);

We need to bypass the authentication by sql injection. But it filters single quote, how to bypass this?

Actually they already gave us a hint:

// parse json and serve static files
app.use(bodyParser.urlencoded({ extended: true }));

But the comment seems wrong, it's not parse json(it should be bodyParser.json), it's to let urlencoded can be parse by qs library which support passing array or even object.

Like this:

username[] = ' or '1' = '1
password[] = ' or '1' = '1

So both username and password is an array: ["' or '1' = '1'"]. And it will be string ' or 1' = '1' when concat with other string.

commented

@kingrootdm Nope, if we use bodyParser.json, we can pass json data like:

{
  "username": ["' or '1' = '1"]
}