The GSR booking website after injecting a script.

How I Hacked Wharton’s Group Study Room Booking System. Twice.

After disclosing this to Wharton Computing, I decided that I would share the thought process that I used to discover two design flaws in the online Group Study Room (GSR) booking system that allow students to override their 90-minute limits for reservations. These exploitations of vulnerabilities, although both somewhat unorthodox, are examples of classic pitfalls in system design.

I tried to make these walkthroughs generalizable so that they require minimal knowledge on coding or the particularities of the system to understand. Trust me on this — you might find the logic behind these two hacks interesting even if you don’t have any technical background or know what the heck GSRs are.

For folks who want to see the trick in action, I have also included a JavaScript code sample at the end. You can execute it in your own web browsers to take advantage of the second vulnerability mentioned.

Disclaimer: The bug that I reported to Wharton’s technology department (in good faith) affects the current reservation system ̶a̶n̶d̶ ̶h̶a̶s̶ ̶n̶o̶t̶ ̶b̶e̶e̶n̶ ̶f̶i̶x̶e̶d̶ ̶a̶s̶ ̶o̶f̶ ̶t̶h̶i̶s̶ ̶w̶r̶i̶t̶i̶n̶g̶. The walkthrough was compiled for informational purpose and as a proof-of-concept only. I have been careful not to abuse this particular bug to my personal advantage or convenience, and strongly suggest that you avoid such exploitations as well. Update on Mar. 14: The school confirmed that the vulnerability had been fixed.

Some Context

Group Study Rooms (GSRs) are study and meeting spaces on the campus of the University of Pennsylvania. Students enrolled in the Wharton School have the privilege to book these rooms that are equipped with computers, large flat-screen monitors, and whiteboards. These rooms are always in high demand, and bookings are usually made at least 24 hours prior. The rules for student reservations are as follows:

  1. Reservations can be made online for 30 minutes, 60 minutes, or 90 minutes intervals.
  2. Students are limited to 90 minutes of total future reservations. Bookings may not overlap with each other in time.
  3. Rooms can be booked at most 7 days in advance.
  4. Booking will preclude other students from occupying the same space, although if students do not arrive in the first 10 minutes of their reservation, other students can “appropriate” or “overbook” the booking from the computer workstation in the room.
Credit: University of Pennsylvania

For the Spring 2019 semester, the school transitioned from the legacy SPIKE (an awkward acronym) website to a redesigned MyWharton web application for making room reservations.

Vulnerability #1: Inverse Bookings

The first vulnerability affects the now-defunct SPIKE system which went into retirement in January 2019. With the caveat of having to execute a request from an in-room computer every 7 days, the loophole allows for unlimited GSR booking time for students rather than 90 minutes from any devices, as long as reservations do not overlap.

Credit: Wharton Computing

After poking around the website ( for a bit, we can get some ideas how browsers communicate booking requests with the server. The following is a typical communication between your laptop and the SPIKE server, for example, to book room G62 from 9:30 PM to 10:30 PM.

Note: if you’re not familiar with the mechanisms of RESTful models and HTTP protocols, just look at the visual diagrams instead and ignore the text above regarding the endpoints.

Booking a room for 60 minutes with no other upcoming reservations.

Let us make some more booking requests on behalf of the web client to explore the application interfaces. When we have 60 minutes of reservation time already booked, the server is smart enough to reject a request that will exceed the 90-minute booking limit:

Dead end.

There is also a different type of communication made between the in-room desktop computers and SPIKE, dubbed “appropriation,” which allows another group to utilize the room if he or she does not show up in the 10-minute grace period after the reservation starts. In the following example, the room can be appropriated after 6:40 if a reservation starts at 6:30 PM:

The “on-demand” protocol from in-room computers behaves similarly to booking rooms from your own devices, but:

Observation #1: Reservations need not respect the 90-minute total booking limit. (Maybe we will be able to take advantage of that.)

Observation #2: Only the current reservation of the room can be “appropriated.” You cannot overbook a future reservation from an in-room computer.

Observation #3: Of course, your new booking still cannot conflict with an existing booking.

So to sum up:

This is more or less as much information as we could gather by just observing the behaviors of the protocols. We need a lightbulb moment to move further. What usually helps me a lot in these cases (besides going for a cold shower) is to think from the perspective of the developer. How would a reasonably negligent clone of myself go about programming these protocols?

  • Condition #1: For any existing reservation to not overlap with the requested booking, the requested booking must either start after the reservation ends or end before the reservation starts. This is a convoluted way to say that the requests may not overlap.
  • Condition #2: The current time must be in between the time when the request starts and the time when the request ends.

How would an illegal booking satisfy these two conditions?

Notice that we made an implicit assumption here about bookings. What if the start time of the requested booking is later than the end time of the booking? This condition seems obvious to us human, but the machine probably doesn’t know better. Why don’t we try booking a room for a negative duration:

We now have a total future reservation time of -180 minutes, which means we can book another 270 minutes of GSRs before reaching our limit. Caution: we only have this privilege before 10:30 PM, when the -240 minutes reservation no longer technically happens in the future. But we can push this a bit further, since we can make reservations at most 7 days in advance. There are 60 ✕ 24 ✕ 7 = 10080 minutes in a week.

Now we can book any number of GSRs before March 22nd without reaching the time limit.

Voila! Booking on April 5 has a duration of minus seven days.

Vulnerability #2: Shifting Timezones

The second vulnerability affects the new MyWharton system that was introduced in January 2019. It requires you to either make the reservation requests manually or run an extension on your browser, and restricts you to 45 hours of future reservations. On the flip side, this will relieve you of the duty to make a weekly request from a GSR computer, and allow you to book up to 30 rooms for the same half-hour time period. Further, bookings made through this cannot be appropriated by other groups even if the reservation holder is more than 10 minutes late.

The new MyWharton definitely looks more modern, although it’s hard to commend its usability. Rules for booking GSRs remain unchanged, although a lot of the internal systems have been improved. The platform employs a Python-backed middleware to prevent cross-site request forgery (CSRF), and a more rigorous booking logic such that Vulnerability #1 no long works. We re-examine by analyzing a typical communication.

Note: the room number and time on the URL do not matter for the POST request.

The starting point of the bug comes from an idea a friend (cheers to Santiago Buenahora) had for the old SPIKE system: if we were able to reserve a room for one minute, we would be able to block others from booking the room for the half-hour period, while only using 1 instead of 30 minutes of our quota.

Unfortunately developers of both SPIKE and MyWharton got there first.

Observe that the booking request violates two rules of valid bookings, since neither the duration nor the end time are intervals of 30. We then make a 30-minute reservation across two 30-minute windows to see if we get the same error message if the request only breaks one of the two rules.

This didn’t work either, but getting the same error message is a hint that we’re onto something.

Although the date in the endpoint URL is a redundant field for making booking requests, the trailing -04:00 provides inspiration for tinkering with the timezone. All the GSRs available through this portal are physically located in Penn’s Philadelphia campus on Eastern Time, but what would happen if the device from which one makes a request is in another timezone? After setting my device to Pacific Time, the request indeed looks different:

A new component was added to the parameter.

Pacific Daylight Time (Coordinated Universal Time minus 7 hours) and Eastern Daylight Time (UTC-4:00) are different by exactly three hours, but there are other pairs of timezones, such as standard times of India (UTC+5:30) and Nepal (UTC+5:45) are only off by 15 minutes.

Let’s go further, and create a hypothetical timezone UTC-3:31 that is ahead of Eastern Time by exactly 29 minutes. A reservation from 8:30 in UTC-4:00 to 9:00 in UTC-3:31 would both begin and end on 30-minute intervals in their respective timezones, but practically only lasts one minute.

We impersonate a device in this newfound timezone UTC-3:31, and make a request again to book for one minute. If it works, we can now occupy this half-hour spot from 8:30 PM to 9:00 PM for the room with only a one-minute reservation from 8:30 PM to 8:31 PM.

Yep. Repeating this request for different dates will allow us to make 90 of these one-minute bookings each occupying a half-hour spot. Our reservation quota is now raised from 90 minutes to 30 minutes ✕ 90 = 45 hours.

An extension of this trick will also allow us to book multiple rooms concurrently: if we shift both the start and end timezones by one minute exactly, we’ll be able to make one-minute reservations for up to 30 rooms within the same half-hour period without any of them technically overlapping.

Booking a second room for 8:30 PM to 9:00 PM

Cementing the above ideas we have ourselves a neat (but dirty) script that can be run on the booking page in web browsers. I have included the code below, but please don’t abuse this — it takes away the fun.

The script also took advantage of a host of XHR, CSRF and referrer validation weaknesses. None of them is fatal on its own, but together they made the code injection possible on web browsers without requiring auxiliary setup or extensions, and obtain the session identifier form the current PennKey login.

The following cURL command is the crux of the bug, although you’ll have to fill in your own sessionid and csrftoken to give it a spin.