← All talks

Insert coin Hacking arcades for fun

BSides Colombia30:22112 viewsPublished 2025-03Watch on YouTube ↗
Tags
StyleTalk
About this talk
Desde niños queríamos ir a los recreativos y jugar horas y horas gratis. ¿Qué tal si lo hacemos ahora? En esta charla os voy a mostrar algunas vulnerabilidades que he descubierto en el sistema cashless de una de las mayores empresas del mundo, con más de 2300 instalaciones en 70 países #ciberseguridad #bsidesco #arcade
Show transcript [en]

I present to you Ignacio, please, a big applause for him. Good morning, good morning. Well, sorry for the voice, last night we were chatting until very late and I just woke up, so let's see what's up. It's the first time I present the talk, so I don't know how long it will last either, it can be 20 minutes or 5 days, so let's see. Well, my name is Ignacio Navarro, I'm 26 years old, I'm from Cordoba, from Río Cuarto. I'm working as an AppSec and I do a little Ethical Hacking. And as an interesting fact, I really like shoes and I also make clothes. But well, let's get to it. This is a bit of the agenda. First, let's see an introduction of how I found it. The

idea is to divide it into 10 stages. One with the part of how the Brazil part was. The Argentine company. An IDOR and Broken Authorization. The part of the Android application. Accounting, Cover and Race Condition. A server that was for Bookings. External servers, but the same. The NFC part and the last one. But well, I gave you the 100% educational talk and all that. If you are doing tickle hacking and find something, report it. Don't deface places to publish things. But report everything and I don't give this talk that it's an example or anything. There are things that were reported, but it's a bit to have that ethic of saying, "Hey, I found something. Okay, I'll report it." Now, yes. Introduction.

Last December I went to the Hacker2Hacker conference in Brazil, in Sao Paulo. It was very good, technically speaking. But the conference also has a lot of parties, so that's the most interesting part. At one of those parties I met a person, and the next day we went to drink something and we passed in front of an arcade, a mall, a shopping mall, and there was a gaming room. And I said, "Okay, let's see what's up." After a beer, it's always good to play for a while. And as soon as we entered, I saw a machine like that, that was used to take out cards, load, see the balance that you have left and so on.

And when I was buying the card, I saw that a very old system was running. So I stayed a while looking at it from the front to see what was going on. And I said, "Well, now I have something to do when I return to Argentina." So, first part, the Arcade Brazil part. I go, I buy the card, it was that one, I cover the name, obviously. I go and search the page, I make a directory bar with GoBuster, normal. I don't find so many things, I know it's a PHP that is running with Drupal. There was the loose PHP info there. I was running a fairly old version, 2019, somewhere there. And I also had the upload zone file, which there is a fairly interesting old reset,

also 2011, that if that is activated, you can upload a file, it is saved in the TMP, having an LFI you can find it and run it. But I was searching, searching, searching, nothing. There was no LFI, I couldn't find anything. I found another server with the same subdomain. I run Subfinder to look for something and it gives me the normal and the plus. There is the QR for the GitHub of Subfinder IDNS. I go to the plus to see what's up and I find a server that is to see the balance sheet, load the balance sheet, a account that I created, see where you played last time and everything. I spent a couple of days trying to exploit it, see if I was lucky. But no, I didn't

find anything. You could only create users. But everything was running after a middleware, so you didn't consume the API directly. So no... There was no luck. I spent two weeks, every day, and nothing. Until I got to a point where I said, "Well, there's no talk." We finish everything here and that's it. But now we go to the Argentina part. I was totally frustrated at home. After two weeks I said, "Well, it's over." I thought about turning the card around to see what was going on. And I saw that there was a date of the manufacturer of that card. And below there was a link. I said, "Well, let's see what's going on on that

side." I enter the page, I search for information and so on. And nothing, it says, "This company is world-wide leader. We have 2,300 facilities in more than 70 countries, etc." I said, "Well, that's interesting." I keep reading. "Not only are we arcades, but we also provide bowling, amusement parks, roller coasters, I said, "Well, this looks much bigger than I was expecting." I went to the client's page and there was the client's map, which was more than 2,300, in 70 countries, etc. I said, "Well, now I do want to see what's going on. I'm going to keep looking until I find something." I also did a DNS sweep. I found that the API documentation part was there. I was in the authentication part,

but I asked for an API key and a token. And the token was: "Hashama 2x with SHA-1, the API key and the API secret." But we didn't have the credentials, so if we wanted to check an URL random, we didn't need anything. The weird thing is that: status access, success false, and then error. We don't have access. I said, "Well, we're using the API B2, what's going on?" Well, nothing. I thought I hadn't practiced it in the talk. We don't have the API key or the API secret. So what happens if we delete version 2 and paste the API directly into version 1? I do the test and it returns 200 OKs with all the locations of that demo, of that URL. This was

the demo page. And I said, well, let's make a barry on the API bar, let's see what we find. There were quite a few 200 OKs with data, some 200 that returned empty, and some 400 with several errors. Or directly 200, as I said before, that says "Status Access", but the "Saxe" says it's false, and it's 400, not 200. I start to see one by one, to see what I can find, and there we get to the IDOR part. What is an IDOR? It's basically when the user has the possibility to choose between a file, through an API or something, and there is no validation of the identity, let's say, "Hey, my document is number

100, give it back to me. Mine is not number 101, but can you give it to me? Well, it's there, give it back to you too." So I went to the card section, I called my card, and they said, "Well, you have $15 left." And well, what happens if I call another card? I call another card, "You have $90." So we already know that there we can see the cards of all the client-server clients. In this case it was the one from Brazil. And the same thing happened with the customers, with the two clients. You called the number 1 and it gave you all the client's data, the name, last name, where he lives, the

photo, the phone number, etc. And that's from everyone. And going back, I mean, you see the history, you can see the cards too, see where I play, and so on. I had made a quick script to see what clients had cards and what cards had balance, so it was like I was giving back all the clients and so on. That being an ID sequence, you could consume them all. And I said, well, but 2,300 places are going to have the same vulnerabilities. It's kind of weird, but yes, I had it. So I said, well, I started looking for more information. And I said, well, the company arrived in Brazil, it exploded, everything went well. In Seche, the Czech Republic, also in Prague, blah, blah, blah.

Saudi Arabia too. Spain, UK. The Las Vegas casino, which has a Russian mountain range, is running the same system too. So at that moment I said, well, by exploding simple things, you can find big places. We are going to keep investigating and seeing a little bit of what's in there. Let's go to the Android part. When I consume the API, I see that it returns me, as it is in the web client part, it is also in the Android application part. And nothing, I had the doubt of seeing, because I searched in the store, nothing appeared. I calculate that it must be due to local restrictions and so on. So I go to pkpure and it appears in all that list of applications. There were like

a lot. So nothing, I download one to see what's up. I make an APK, all the comparison javascripts that you use, it returns the index, but it was kind of complicated to read the javascript, so we need to make it a little nicer, the best syntax. I download JSVuter, which is basically a syntax corrector, nothing more. And there we can make a grep, in this case the API key, the API secret, the URL, the account code and so on. And nothing, since it's all in plain text, it wasn't encrypted, it wasn't blurred or anything, we can see the values of all that. So I downloaded other applications to see if it was more or less

similar to what was happening. And yes, they had everything free. They had the account code, which is what made reference to the central API, since it was the same for everyone. The API key and the API secret, all different. So, to summarize a little, we have the same endpoint that all applications consume. We have the header, which is the account code that says, well, I'm the company from Argentina, I'm the company from France, etc. So with that data we can consume in the name of the company. But nothing, we don't have the account code, since it's an excess of 13 characters, it's kind of complicated to find it. But we have the customer list and we have Google. So if we google a

little, what is the API of that company, of that place, we can consume it without the account code. That would be, summarizing it a little, We call the central API with the account code and it tells us, "Here it is, you have this place, Quito, Ecuador." But that's with a number. If we look for the place in Ecuador, the place, the API, and we consume it directly with that API, it tells us "OK" and it gives us the same data. So we can consume the API directly from the place without having to look for the account code. Loading credit on the card. We go back to the API documentation. To authenticate we need the API key, the API token. 2 times with SHA1. We generate that, we

hit it and it returns the central token, let's say, which is to be able to do the activities. I start to see a little bit of the endpoints that there were and there was one that returned you the whole list of services, of offers, let's say, of products that they sold. In this case nothing, 200 dollars, we give you 50, etc. I go back to the documentation and it says, well, with this you can generate a sale manually. This is the body, you can pass it wherever you want. And for the things that are credit, ticket, bonus, etc. You have to put the parameter "deliver true" so that it is executed automatically. But obviously I didn't execute this because 200 dollars in Argentina is enough. And I didn't want

to have any problems. Looking a little more at the APK, I made a list of all the endpoints that were out there. There were about 30 in each one. They were all in the text-to-plan. and it would come with the data of what the body of each thing is. So, in this case we have the updateCustomer, which consumes the API, etc. It's a type of JSON. There it says "authorization better", which there it asks for the token generated previously, but since we are consuming the API in version 1, that token is not needed. We have the post body, which was the name, the last name, the email and the newsletter. I was very interested in

the email part, since we can do actions without being authenticated. So, what happens if we change the email of a user without having the token directly? So I said, well, let's see what's going on here. Now we go to the account and code part and the rescondition. Account and code basically is to make a charge or join an other person's account. In this case I created a demo account with a webhook email. I make a get, it tells me, well, this is your ID, the name, the last name, etc. Now I make a post to the same ID, but I pass the data that I want the email to be a full test. I hit 200 OK, the email changed. So I said, well, let's do

the demo now of the account and cover. Basically we go to the portal, we log in with the Futes account that we had created before. There we see that it says, demo name, account and cover, a profile picture. We go to our webhook, we go to the endpoint, we hit it. It says, well, it changed with success, everything is OK. We return to the login. We don't know the key because it would be a random account in theory. We reset the key, our mail will arrive. Bank for a while. We reset the key, we put the key we want, since it would be a random account. It will tell us, "Well, everything changed well, excellent." We are going to log in now with this new credential

that we put.

And this is a random account, but I could do it directly in any of the other users and people will not realize unless they enter, obviously. But that you changed the mail or that you changed the password. Let's say it's the same account as before, but with another different mail. We didn't have to put any token or anything in the middle. So nothing, that can be exploited very easily and there is no validation of anything. Race condition, which is basically when several requests, several requests consume the same server and the same object at the same time. And if there is no validation, you can get to see different problems. It is usually seen a lot in the GIF card part and so on. There is the port suger

QR, there is a lot of interesting laboratories for that. There is also a bonus part, of rewards tickets in the application. In this case it says: "Enter the application, you have 300 tickets." I made a very basic script in Python that I sent a couple of threads and so on. I send that, I go back to hit hit hit, it hits five or six times, and when I go to see the history, it could be applied quietly six times, and we have three times six. There it goes. But nothing, in this case it was in tickets only. But let's go back, let's go see the US application, and it says: Here you can give $100, $50, etc. So if we execute it, there is some interesting currency there. But

this is not exploited, because I don't want to have a problem either. Bookings. Looking at the application, I find that there is a part that said "online booking". Well, let's see what it is. I have no idea. And basically it is a page where you can book the place to go play, knowing the number of people who are going to go and so on. So I made a directory neighborhood, I found several open things. The most interesting part was the TMP, Uploads and Data. In the TMP part, there was a lot of data in XML. It gave us a bit of the commands that were there, of the IP addresses and the body that was used to communicate. But nothing so big and interesting. Then for the upload part,

I made a little script to make a scrap of the page, since there were several directories within one. And I put that a little sign pops up that tells me that there may be something here. In this case, it found three folders that said "Argentina Inflation". and generated XMLs. I'm going to see what's up. And I find two certificates in each folder, which are the ones used in Argentina for electronic invoicing. So with those certificates you can already invoice the name of the company. And since the certificates were there, the invoices had to be somewhere. So in the data bar were all the invoices that were generated in Argentina, with the customer data, name, address, amount paid, etc. So there was a lot of data. Booking Manager.

There was something to handle that part. I do a scan and find that. It says "reservation". Search by name and last name, the reservation code. But if you sent it directly without anything, you could see all the reservations that were there. I thought they were old, but in the end they were from now. This was when I was writing it, in March. And there too, there were several errors, there were several SQL injections, there were several development errors that gave you a little information about the server. You could see, modify the amount you would pay. Several things could be done from that side. Information from the people too, from all the people who were going to go to that place. The part of the 6 servers. How do I

go so fast? Well, the part of the 6 servers. There was the public sendes, which was the part to generate tickets and view the documentation. You could create a user directly, there was no validation of any kind. So I created a random user to try. And there were several videos that taught you how to do X things, how to create the configuration of this server, how to create the configuration of the Totem that we saw before. And in the videos there were several credentials, well, I don't know if you can see it, but there was the endpoint, the user and the password. There were several API key that we had seen before. So we had the IP, we had credentials, people's emails. Then, looking a little more, there

was also the amusement park in Spain, it's a big chain there. It had a console that gave you all the URL of the login page. The login part was quite safe, at least for the random user and it didn't log in. But the peculiarity of this was that it had the webpack exposed. So it was all done in Angular. And I started to see the code that was there. And also several APIs. There were all the APIs that consumed. In this case there was an API that listed all the games. Then there was another that let you pay for the games. And looking at the code, I see that there is the difference of roles, it tells you the different permissions. But there was also a part that was

the login, for when you log in. And it tells you, if it returns you 200, it's ok, put the credentials and it's ok. But if inside what we saw before, that the server did not return you the error, but that the JSON inside tells you that there was an error. If it tells you 407, do this. And if it tells you 420, do this other. And I said, well, let's see what 420 is. When it gets there, it tells you to restore the user password. Not without validation either. So it's going back to what we saw before and exploiting that part again to change the password. The NFC part, to finish. I'm not going to explain in detail what NFC is. There is a blog by Jim

Alonso that is quite interesting and explains point by point how the exploitation of cards is. In my case, I read it with the flipper, which is a touch. The card and the flipper were already there. And there we get the card type, which is a MyFresh Classic. The ATK and the SAC, which is the ISO part, the compliance, let's say, that tells you the type of card, the manufacturer and so on. The data. There are 16 blocks. The first 6 are... Every 4 blocks, every 4 spaces, the first 6 are the first key. The second are the access bits, and then the other key. And then you have 3 data blocks. In this case it

was more than anything empty. There was a part that had a couple of numbers up there. And when I echo that and pass it directly to ASCII, it's the card number. I go and validate the card number back. It's exactly the same. The pin number, I didn't find anywhere that it's validated or anything, it never asks for it. So, the A and B key were by default. The card was empty. And we had the card number, so we can replicate it and change it quietly. Then I was also reading the code of the application a bit. And I saw that there was a part that referred to NFC. And it also said that if you had IOS you couldn't use it, I don't know why. And I asked

my dad's phone to see what was going on. And when I tried to tell him about that old woman I had with a card of mine, the idea was to see what that was. In this case, when you log in, it asks you to log in, it asks you the data. and it gives you the possibility to emulate the card with your phone. So if we put this with the account and cover, we can have access to all the cards without the need for a flipper or something. Directly with our Android phone we can emulate all the cards. Now we are about to close. For the end, I was looking a little about the application,

about the system here in Colombia. And I was surprised by the number of clients there were. There were like 31 more or less in different cities and in some cities there were more than one. Since it is not only Arcade, but they are amusement parks, bowling, etc. So that's pretty interesting. And then the conclusions. In 2024 we can still find very, very basic things like this. A part of the EPSICOP culture could help us a lot to be able to fix these problems and see it at the development time and not have to wait until the end to be able to fix it. Education and security for all the environments of the company, the usual. What I said before, if you find something, report it. Don't do bad

things. And if someone reports something, pay a little attention and answer the mail. Sometimes that happens a little, let's say that one sends, you can say, "Hey, I found this with the best of the waves, I don't want to take advantage of anything, we're not talking about coins, I just want to tell you, hey, I found this, there is confidential data, fix it, if you need it, I'll help you." That's what I always send. But there are cases where there's no response from anything. Well, the one from DSP last year, after many emails, they fixed the vulnerability at the end, but they didn't answer me. That's it, we saw it. The same thing happens now with this one.

I sent several emails and nothing. So, nothing, keep insisting until they fix that and change that security gap. But we're here. That's it. Thank you very much.

- - I set 100 threads to try it, but you can set the amount you want. And the number of threads of the processor is set. So it didn't matter, I could send n threads and I would get n times. Thank you.

Good morning. Under the ethical context, understanding that everything is governed by norms, all the exercises you do, all the exercises you showed us, how do you cover yourself in the face of that ethical context? The fact that you report, you are putting the face of "I was the one who did all the scanning, the one who did this" is an exploitation, it is already illegal to do an exploitation without consent. What are those measures that you take to ensure that your exercise, where you are doing it under, I'm going to say, a white hat because you really didn't want to exploit, you did the reporting process, um I don't hide with VPN or anything like that. Have you had any bad situation

with this kind of exercises in your specific case? With any company that hasn't taken it in the right way? No, luckily, or they take it in a good way and they say, "Well, thank you very much." I've had a case in a university there in Argentina of helping him. They say, "Hey, well, how can we fix this?" But no, bad, no. The only thing is that sometimes they don't answer you. I don't know why it will happen, but... I think it depends on each one's ego, on who gets that problem. Thank you very much. At the moment they have always fixed it, but I have had friends who have had that happen, who say, "No, well, it's a feature." And it stays there,

and in his case he had to go to the news to expose it, since he put confidential data from a lot of people, it was about the DNI issue. But yes, at the moment I didn't have to say, "Well, it's like that." How do you come up with the ideas to do these researches? How did you start? What is the point? In the bar, with beer and then you go to the arcade. But I always try to look for something that catches my attention, let's say. That's why I don't know either. I know that Back Bounty is something very big and good. But the part of having to investigate about something that is different from what I use

daily, it gives me a bit of laziness. That's why I try to look for something that I use frequently. Any other questions? Well, you know, I don't ask him, I know he's going to be at the party. If you have any other questions, he's going to be there or if not, anywhere at the event. Ignacio can answer them. Thank you very much, Ignacio. A big round of applause.