Carbender

Contents

Carbender#

Helpers#

import os
import requests
from datetime import datetime, timedelta
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.environ["API_KEY"]
URL_QUERY = "https://%s.crucible.dreadnode.io/score"
URL_FLAG = "https://crucible.dreadnode.io/api/challenges/%s/submit-flag"
CHALLENGE = "carbender"

def query(data):
    response = requests.post(
        URL_QUERY % CHALLENGE,
        headers={ "X-API-Key": API_KEY },
        json={ "bookings": data }
    )
    return response.json()

def submit(flag):
    response = requests.post(
        URL_FLAG % CHALLENGE,
        headers={ "X-API-Key": API_KEY },
        json={ "challenge": CHALLENGE, "flag": flag }
    )
    return False if response.status_code != 200 else response.json().get("correct")

Solution#

If we submit a booking for 2023-05-29 (a Monday) we can see that the car rental prices are fairly consistent with the only differences for a single car type being that weekend bookings are more expensive.

data = [
    { "car_type": "luxury", "date": "2023-05-29", "action": "book", "created_date": "2022-05-01", }
]
query(data)["prices"]
{'sedan': {'2023-05-29': 119.0,
  '2023-05-28': 139.0,
  '2023-05-27': 139.0,
  '2023-05-26': 119.0,
  '2023-05-25': 119.0,
  '2023-05-24': 119.0,
  '2023-05-23': 119.0},
 'suv': {'2023-05-29': 159.0,
  '2023-05-28': 179.0,
  '2023-05-27': 179.0,
  '2023-05-26': 159.0,
  '2023-05-25': 159.0,
  '2023-05-24': 159.0,
  '2023-05-23': 159.0},
 'luxury': {'2023-05-29': 189.0,
  '2023-05-28': 209.0,
  '2023-05-27': 209.0,
  '2023-05-26': 189.0,
  '2023-05-25': 189.0,
  '2023-05-24': 189.0,
  '2023-05-23': 189.0}}

However, if we submit and cancel a booking on a Monday prior to 2023-05-29 we can see that the booking price for 2023-05-29 will decrease slightly.

data = [
    { "car_type": "luxury", "date": "2023-05-22", "action": "book", "created_date": "2022-05-01", },
    { "car_type": "luxury", "date": "2023-05-22", "action": "cancel", "created_date": "2022-05-02", },
]
query(data)["prices"]
{'sedan': {'2023-05-29': 119.0,
  '2023-05-28': 139.0,
  '2023-05-27': 139.0,
  '2023-05-26': 119.0,
  '2023-05-25': 119.0,
  '2023-05-24': 119.0,
  '2023-05-23': 119.0},
 'suv': {'2023-05-29': 159.0,
  '2023-05-28': 179.0,
  '2023-05-27': 179.0,
  '2023-05-26': 159.0,
  '2023-05-25': 159.0,
  '2023-05-24': 159.0,
  '2023-05-23': 159.0},
 'luxury': {'2023-05-29': 186.54,
  '2023-05-28': 209.0,
  '2023-05-27': 209.0,
  '2023-05-26': 189.0,
  '2023-05-25': 189.0,
  '2023-05-24': 189.0,
  '2023-05-23': 189.0}}

We are allowed to book and cancel up to seven times so we can repeat this process for seven Mondays prior to 2023-05-29 to decrease the price as much as possible. This will give us the flag.

date_booking = datetime.strptime("2023-05-29", "%Y-%m-%d")

date_create_booking = "2022-05-01"
date_create_cancel = "2022-05-02"

data = []
for weeks in range(1, 8):
    date_booking_new = (date_booking - timedelta(weeks=weeks)).strftime("%Y-%m-%d")
    data.extend([
        { "car_type": "luxury", "date": date_booking_new, "action": "book", "created_date": date_create_booking, },
        { "car_type": "luxury", "date": date_booking_new, "action": "cancel", "created_date": date_create_cancel, }
    ])

response = query(data)
print("Flag accepted:", submit(response["flag"]))
Flag accepted: True