phpoor

phpoor implements a secure connection with a PHP web server. Both the server and a graphical client are provided.

It is released in the public domain.

It is very young and might completely fail to work with your setup.

Introduction

phpoor is masterpiece of hackery! (yes I dare)

Secure communication is a solved problem. Just use some well known protocol or software like ssh and you are done.

Sure.

Except that what to do when you MUST use an insecure channel, when you MUST connect to an insecure HTTP server, POP server, FTP server, whatever server, huh?

For example, here at free.fr we have to update our website through an insecure FTP server. There is no SFTP stuff available. For the emails it's the same. Just a poor POP server which exposes all our emails to the world. There is the APOP stuff to not expose the password, but that's not enough. To send emails you must go to a web server, and there again, no HTTPS, and there again the password is sent in clear, and the emails as well.

i WANT to update my website everywhere. I want to read my emails everywhere. I even want to surf securely (not exposing what pages I see to people around; imagine a WIFI spot) everywhere.

Thanks to free.fr that hosts my stuff for more than ten years for free (thanks to them for that by the way), I can put PHP files here. That means I can put a secure endpoint, by implementing some secure protocol in PHP.

I thus have a secure connection over an insecure HTTP link. What can I do with that? Whatever free.fr allows our PHP code to do. When writing this page (2009-01-23) I can open/read/write/close files on the server, meaning I can update my website (by the way, rmdir does not work, if you work at free.fr, please do something; rmdir does not work in PHP, thanks). I can also use socket/connect/shutdown, meaning I can surf the web (and so read and send emails) (this does not work with every website and every request).

The link between my site and the rest of the world is not known to me. Maybe it's much more insecure than a direct link to the world. That's the biggest limitation of the exercise.

But it still remains a masterpiece of hackery! (yes, I still dare)

Features

Features are unlimited. All what your PHP server has the right to do can be done. Just modify the server and the client and you are done.

Here is what is currently implemented:

Updates can be incremental. You can put/get very big files by small pieces. This is very important because by FTP, if a connection breaks, I must restart from scratch. With my stuff, I simply restart from where it stopped. At the end, the SHA1 of local and remote files are compared, to be sure everything was transmitted and stored as expected.

Download

phpoor-0.9.5.tar.gz (2011, july, 11th)
Minor stuff: use system's colors.

phpoor-0.9.4.tar.gz (2010, may, 31st)
New functionality: upload, to throw many files on the website quickly, with no GUI interaction. Does not verify the SHA1 of uploaded files, so not very safe. Just a quick hack. Maybe I'll fix that at some point in the future...

phpoor-0.9.3.tar.gz (2010, january, 18th)
A new functionality: backup, to download your website, to have, well, a backup. And a little bug fix too (gtk, no big stuff).

phpoor-0.9.2.tar.gz (2009, march, 14th)
A stupid bug in the 0.9.1. Don't use the 0.9.1 anymore, it's not secure. Fucking shame on me...

phpoor-0.9.1.tar.gz (2009, january, 30th)
The protocol has been improved a bit. Security should be slightly better.

phpoor-0.9.tar.gz (2009, january, 23rd)
This is the initial release. It works for me. It may fail for you. There are many potential issues. If it does not work, contact me, maybe I can help you. It should work with PHP 4 and PHP 5. The client should work under POSIX systems (GNU, Linux, BSD, whatever) and Windows (for I only have a Windows box at the moment). It uses GTK for the GUI (you need gtkcooker if you want to hack the GUI).

README

Here comes the README from the distribution.

This is phpoor, a secure connection to a PHP server.
You can:
- update a PHP powered website using a secure protocol
  through the use of SALSA20, a stream cipher from Bernstein,
- have a secure HTTP proxy: the client sends HTTP requests to the
  PHP server that handles them and returns the reply from
  the wanted request (useful to surf in public places;
  nobody sees what you surf; in fact it's the PHP server
  that surfs, so it must be configured to allow sockets),
#email sending not implemented yet.
#- send emails over an insecure network by throwing them
#  to the PHP server and letting it send them for us
#  (your PHP website has to allow the use of the 'mail' command).

You can add functionalities. Everything the PHP server is allowed
to do can be exported to the world. The client has to implement
the desired functionality too. Design a simple client/server
request/reply and you are done.

It is released in the public domain.

To build, first go in key/ and generate key and key.php.
Then, put all the files in server/ on a directory on your website.
Put also key.php. You will need some secure way to put it
just in case someone catches it and fucks up your website
later on.

If your server is a 32b host, copy salsa20-7-32.php to salsa20-7.php.
If your server is a 64b host, copy salsa20-7-64.php to salsa20-7.php.
Only Intel ia32 running Windows and a 64b box (Intel or AMD I think)
running GNU/Linux have been tested. The PHP SALSA20 implementation may
completely fail to work. Copy salsa20-1.php to salsa20-7.php in case of
trouble. This one should work everywhere (but will be much slower).

Note that it's a good idea to choose some sort of "random"
directory to put the PHP files. It's also a good idea to
rename phpoor.php to something else. If the program has
bugs, it's very risky to use. So to use weird URLs is
a way to mitigate possible automatic attacks that will
only look for some known places, like "/phpoor/phpoor.php."
(Of course, live attacks are still possible, since you
send the URL of the server in clear in your HTTP requests.)

Go in client/ and do make. It will ask you some questions
about the PHP server.

The client uses gtk. It should work on Posix systems (linux, *bsd, ...)
and Windows.

The client is keyboard-friendly:
- up/down/page up/page down to scroll the current list
- shift + up/down/page up/page down to scroll the bottom window
  (the log window)
- TAB to switch from local list to remote list
- enter to go to currently selected sub-directory.

Once a file is selected you can put/get it to/from the server.
If there was a problem you can resume a transfer.
Files are verified once the transfer is finished by calculating
SHA1 locally and comparing with remote SHA1 returned by the
server.

It should not be too hard to make a recursive put/get.
If you need it, ask, I may do it. If you did it, send
your code for everyone to enjoy it.

The client may act as a local HTTP proxy.
Run "client -p <port>" and the client will be a HTTP proxy
forwarding HTTP requests to the PHP server that will execute
the command and report back the result, all through a secure
channel!

In case of problems, contact sed@free.fr

http://sed.free.fr/phpoor

SECURITY

Here comes the file SECURITY from the distribution, explaining the protocol.

I think I use SALSA20 the best I can. Maybe not, I don't know. And maybe SALSA20 is broken... (But Bernstein is funny, let's trust his hard word.)

Is this stuff secure?
I don't know, I am not a cryptographer nor a cryptanalyst, just a poor
hacker.

Let me explain how I encrypt data for you to decide if it's
secure or not.

The client and the server exchange messages.
Each message is encrypted.
We use the SALSA20 cipher with keys of 256 bits.
SALSA20 has an IV of 64 bits and a block counter of 64 bits too.
We just use those two stuff to make a big block counter of 128 bits.
We increment the counter after each and every block's encryption.
(This leads to a limitation of the protocol. Only one client
can connect at a time. The counter is global. That's not a big
issue for me, might be for you.)

Note also that you can encrypt 2^128 blocks (which are 64 bytes
long). After that you should change the key. I think it's a
rather big number of packets. I doubt I will ever send as
much blocks in my whole life, so I didn't implement any
protection against an overflow here. That's a security
hole. Especially since the client can request the server
to increase its current counter. (Why this possibility?
Because a client's packet may get lost and the client will
then have to send a new one, which she will do with a new
IV, which she must inform the server, that waits for a
lesser IV.)

Data to send is first appended with "random" data (we use the rand()
function in the client and mt_rand() in the PHP server, this is not
very random, I know), 20 bytes of random. We then append an HMAC
(SHA1(key, SHA1(key, message)) to the stuff to verify at reception that
the packet is a valid one. Then we zip all that with zlib.
We then add some more random data at the end, at least 8 bytes.
The result is 64 bytes-aligned, to limit the leaking of information
(even if someone cannot see what you send, she can see that you send
something and, based on the length of what you transmit, may
get some information on what you do). Of course it's not
perfect, and some information leaks anyway, but it's a little
help, maybe not big... We then add some (between 0 and 64, which
is also a random decision) random bytes at the
head and at the end (to keep the 64 bytes alignment) so that
an attacker has a harder job at analyzing data she receives. She
won't know exactly where real data starts. It can be byte 0, but
it can be byte 64, and anything in between. I don't know if it
adds security or not, maybe. I don't think it removes security,
so it does not hurt in the worst case. Legitimate receivers
just try to unzip the data starting at various bytes. It can
only succeed at the right byte. In the worst case, it only
increases CPU usage at reception.

Then the data (with random, HMAC, compressed by zlib, and a bit
of random at the end and the start) is encrypted with the key
and big counter (incremented at each 64 bytes-block of data).
And then it is transmitted as a file in the HTTP protocol (or
is it MIME?).

So be it. Secure? Not secure?

I think it is as secure as SALSA20 can be. We never ever encrypt
twice with the same key stream, because the counter is incremented
at each encrypted packet, by the server or the client. And we
add some randomness. And we compress data to remove redundancy
in data. Sure, zlib is not the perfect compression scheme and some
bits of its output are well known, but it helps removing redundancy
(and also helps reducing bandwidth consumption). And we add
an unknown number or random bytes at the head for an attacker to
have more work when analyzing packets she gets.

In the current implementation, if the client or the server
crashes the same IV might be used twice, but I doubt it
will ever happen (or very infrequently) (and I guess the
probability to crack the server or the client by other
means is higher, so it's not an issue) (but I didn't prove
anything, so you have to trust my words, which is not a
good idea, we talk about security here, you know, paranoia).

Anyway, this tool is for my private use. I am not a State nor
a private company, nor a "bad guy," so my secrets have no
value. I just want to be able to update my website from
everywhere with no trouble from dummy crackers and wanabee
script kiddies hanging around. I also want to surf without
eyes around to see what I surf. (Sure if I am in a public
place, the screen is visible, and even if I am not in a
public place the screen emits some electromagnetic waves
that can be decoded, but it's hard stuff, countrary to
something like WIFI spying which is very easy.)

So I guess I am secure enough to fight little beasts that would
want to attack me.

A little patch

Charles Pritchard sent an email a few days ago (writing 2010-03-16) to unify 32b and 64b versions.

Hello,

I've worked a little with your port of the Salsa20 code;
it seemed like a simple check for the PHP INT Size in the add loop allows
it to work in both 32bit and 64 environments.

The while loop is kinda unnecessary; but anyway:
function myPLUS($v,$w) {
   $x = ($v + $w); // & 0xffffffff;
   if(!is_float($x)) return $x;
   if(PHP_INT_SIZE < 8) {
         while($x < -PHP_INT_MAX-1) $x+=(PHP_INT_MAX+1)*2;
         while($x > PHP_INT_MAX) $x-=(PHP_INT_MAX+1)*2;
   }
   return (int) $x;
}

Contact: sed@free.fr

Created: Fri, 23 Jan 2009 13:00:14 +0100
Last update: Mon, 11 Jul 2011 17:53:19 +0200