Tag Archive: php


I suppose I better write about this now, as I encountered these errors a while ago, and the details already started slipping my mind. So, what’s happening? I am writing some PHP code. As a testing server, I’m using my ODROID U3. An ARMv7 board, running ArchLinuxARM. Therefore, we have a 32 bit machine running PHP 5.6. Now, the (soon-to-be) production server is an x86_64 machine, running Ubuntu 14.04LTS. So, this is a 64 bit machine running PHP 5.5.

Let’s have a look at the mcrypt_create_iv() function. This function produces random data. Now, there is a change introduced in PHP 5.6.0. First, let’s have a look on how random data works on a Linux platform. (Other *NIX platform might differ from this)

/dev/random Gives random data, and blocks until there is enough entropy available.
/dev/urandom Gives random data, but never blocks. This means possible less entropy in the result.

Basically, we’re interested in the most possible entropy when we’re doing crypto, then we use /dev/random. That’s why, for example, generating PGP keys takes so long. It’s just waiting for enough entropy to become available. When we need some randomness in a setting that doesn’t require crypto-grade entropy, /dev/urandom is sufficient.

Now, back to PHP. We have the mcrypt_create_iv() function to generate random data. Now, what happened. Since PHP 5.6.0 the default source for randomness is /dev/urandom. In prior versions it was /dev/random. So…. what happens? Code that runs fine on the development machine hangs on the production server, as it’s waiting for entropy. That’s not what we want to happen on a website. So, when using the mcrypt_create_iv() function, always specify the entropy source as the default differs per PHP version.

Well… the difference between 32 and 64 bit PHP versions, it’s all in the size of the int, or rather, using the PHP_INT_MAX for purposes it wasn’t intended for. So, we’re looking at setting a cookie. The idea is to have a “stay logged in” option, so we set the cookie to a date/time way in the future. Considering the Year 2038 problem, the INT_MAX for 32 bit, results in 19 January 2038. However, this is far enough in the future to be used as a “remember me” function. As systems turn 64 bit, this problem is solved, and why not setting the date even to a later date? It just needs to be way ahead in the future to simulate a “never expire” cookie. Well… let’s have a closer look on how cookies work. In PHP, the setcookie() takes a unix timestamp, so, it’s just an INT value containing the number of seconds since the epoch (1 Jan 1970, 00:00 GMT). So far so good, so, if we give it the maximal int value for a 64 bit int….. we end up 293 billion years in the future. (The English Language uses the Short Scale for Numbers, where Continental European Languages uses the Long Scale, note this is “293 miljard” in Dutch. See “Names of Large Numbers” on Wikipedia) So, we’re setting a cookie to a date probably beyond the end of the universe. So, basically, it will never expire. That’s the intention, so…. what went wrong?

Setting a cookie to a date where it will survive the end of the universe causes issues with the Year 10000 problem. The problem is, the server doesn’t just sent that number to the client, it sends a formatted string, it’s format is Wdy, DD Mon YYYY HH:MM:SS GMT Spot the problem? The year is encoded as YYYY, meaning 9999 is last year it supports. So…. setting a cookie to the end of time is not an option.

I don’t know how many 32 bit clients are still out there, but considering the fact they might suffer from the year 2038 problem, I suppose it’s safer to use 2038 as the the-end-of-time value.

Hello peoples,

Now that I am graduated, as mentioned in previous post, I am working on a project for my university. Well… today I also started working on one of my own projects again, the WordPress OAuth plugin. I am extending the plugin with features like sorting of buttons, and separating the OAuth code from the general code, to prepare support for other authentication schemes such as OpenID and Persona.

Once the separation code has been completes, it should result into two separate plugins BlaatSchaap Auth for the general code and BlaatSchaap OAuth for the OAuth specific code. This also introduces a problem. When current users upgrade to the next version, BlaatSchaap OAuth is upgraded, but then requires the BlaatSchaap Auth plugin. How to I install the BlaatSchaap Auth plugin automatically during the BlaatSchaap OAuth plugin upgrade. I have been googling about this issue, but without result. Is there an official way to do things like this or should I just hack some code together to do this trick?

Anyhow, tomorrow I’m having another party. Yeah, I am celebrating my birthday more then once this year. Party time! lol.

A known XSS attack is using echo $_SERVER[‘PHP_SELF’] in forms. More about this problem on stack overflow. Anyhow, recently I have been working on a project, where I was to extend existing PHP code, and I noticed this vulnerability to be present in the code. As this is a case of “replace string in all files”, this can be solved with a single command.

However, it sounded much simpler then it was. I must admit I have little experience with regular expressions, or the differences between the regular expressions in perl and sed, as the following expression worked in sed but not in perl. Another problem was escaping, especially in my previous failed attempt that was using -exec as find parameter.(As recommended here) That would need double escaping and such. Way too messy, therefore, xargs looks much cleaner. Anyhow, the following code is working:


$ find directory -name "*.php" -print | xargs sed -i  "s/<?php echo \$_SERVER\['PHP_SELF'\]; ?>/<?php echo htmlspecialchars\(\$_SERVER\['PHP_SELF'\], ENT_QUOTES, 'utf-8'); ?>/g;"

My server Pi, well… it still needs some server stuff to be installed. Installing git has been forever on my TODO list. One of the things that are supposed to be handles by this git server is nightly backups of my dedicated server, which hosts this blog among a number of other sites. Originally, my BeagleBoard was supposed to have this role, but due its instabilities, I have never set it us as a git server. At some point in time, Eileen wanted to set up a server at her place, and asked me to help her with configuring it. So I asked if I could have some space on that server for backup purposes. Unfortunately, that machine was unstable as well, so it shut down as well.

To manage git, we’re going to use gitosis. The very same way as is done on my dedicated server (at ovh). But we’re going to use a different configuration. The ovh server exports all repositories, while here we’re going to set up private repositories. But we also want to have the possibility to have public repositories. We will also configure gitweb to have a nice interface to those public repositories.

This configuration is performed on a Raspberry Pi running ArchLinuxARM. However, this guide could be applied to regular ArchLinux on i386 or x86_64 as well.

Let’s get started, shall we?

[andre@rpi-server ~]$ yaourt -S gitosis-git

We have to create set the home directory for the git user manually:

[root@rpi-server home]# mkdir /srv/gitosis
[root@rpi-server home]# usermod -d /srv/gitosis/ git

Since we’re hosting this on a raspberry pi, and don’t want to store the repository on the SD Card, we’re going to apply the same method as we’re dong during the setup of the NFS shares: We add the following line to our fstab

/home/gitosis   /srv/gitosis    none    bind    0   0

Which basically means we mount the /home/gitosis directory to /srv/gitosis. Of course we could simple have made a symlink as well. Anyhow, let’s continue.
***** TODO **** use a symlink after all???

[root@rpi-server home]# mkdir /srv/gitosis
[root@rpi-server home]# mkdir /user/gitosis
[root@rpi-server home]# mkdir /srv/gitosis
[root@rpi-server home]# chown git:git /srv/gitosis
[root@rpi-server home]# chown git:git /home/gitosis/
[root@rpi-server home]# mount /srv/gitosis

Now, I am going to initialise gitosis. I will do this as the git user. So, I su to root and then to git, like this:

[andre@hplaptop ~]$ su
Wachtwoord: 
[root@hplaptop andre]# su git
[git@hplaptop andre]$ cd
[git@hplaptop /]$ 

I have placed a file in the home folder containing my public key. I will try to initialise gitosis using this key:

[git@rpi-server gitosis]$ gitosis-init < andre\@hp.pub 
fatal: unable to access '/home/andre/.config/git/config': Permission denied
Traceback (most recent call last):
  File "/usr/bin/gitosis-init", line 9, in 
    load_entry_point('gitosis==0.2', 'console_scripts', 'gitosis-init')()
  File "/usr/lib/python2.7/site-packages/gitosis/app.py", line 24, in run
    return app.main()
  File "/usr/lib/python2.7/site-packages/gitosis/app.py", line 38, in main
    self.handle_args(parser, cfg, options, args)
  File "/usr/lib/python2.7/site-packages/gitosis/init.py", line 136, in handle_args
    user=user,
  File "/usr/lib/python2.7/site-packages/gitosis/init.py", line 75, in init_admin_repository
    template=resource_filename('gitosis.templates', 'admin')
  File "/usr/lib/python2.7/site-packages/gitosis/repository.py", line 54, in init
    raise GitInitError('exit status %d' % returncode)
gitosis.repository.GitInitError: exit status 128

Apparently, it tries to access file in my (andre) home directory, while its running as git. It shouldn’t know about me, right? Well….

[git@rpi-server gitosis]$ set | grep andre
MAIL=/var/mail/andre
XDG_CACHE_HOME=/home/andre/.cache
XDG_CONFIG_HOME=/home/andre/.config
XDG_DATA_HOME=/home/andre/.local/share

So, there is still a reference to my config directory in the enviorement, lets unset this shit and continue:

[git@rpi-server gitosis]$ unset XDG_CACHE_HOME
[git@rpi-server gitosis]$ unset XDG_CONFIG_HOME
[git@rpi-server gitosis]$ unset XDG_DATA_HOME

Now, we can initialise gitosis:

[git@rpi-server gitosis]$ gitosis-init < andre\@hp.pub 
Initialized empty Git repository in /srv/gitosis/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /srv/gitosis/repositories/gitosis-admin.git/

Now, we're going to install and configure the web server:

[andre@rpi-server ~]$ yaourt -S apache

We're going to do the mount bind again

/home/http   /srv/http    none    bind    0   0
[root@rpi-server ~]# mkdir /home/http
[root@rpi-server ~]# mount /srv/http/
[root@rpi-server ~]# chown http:http /srv/http/
[root@rpi-server ~]# chmod g+w /srv/http/

I'm going to add myself to the http group.

[root@rpi-server http]# groupmems -a andre -g http

As I've mentioned before, I wish to host gitweb as well. Gitweb is in the git package, so it's already installed, just making a symlink is enough, which I can do as myself, as I am in the group http. I've also downloaded the "unknown" folder from my ovh server, which is the page that displays the "domain not served as this server" page in case an unknown vhost is requested. I will move this as well:

[andre@rpi-server ~]$ ln -s /usr/share/gitweb /srv/http/gitweb
[andre@rpi-server ~]$ mv unknown /srv/http

As the fact I am putting my "unknown vhost" page on this server, it will be supporting vhosts. If a requested domain doesn't match any VirtualHost in the apache config file, it will serve the first entry in the config file, therefore we will edit the config file /etc/httpd/conf/extra/httpd-vhosts.conf and put the following in

NameVirtualHost *:80

<VirtualHost *:80>
    DocumentRoot "/srv/http/unknown"
    ErrorLog "/var/log/httpd/unknown-error_log"
    CustomLog "/var/log/httpd/unknown-access_log" combined
</VirtualHost>

However, Virtual Hosts aren't enabled yet. We need to edit the main config file in order to include the vhosts config file. We need to open /etc/httpd/conf/httpd.conf and uncomment the virtual hosts line:

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

The "unkown vhost" page is written in php, so we're also going to install php:

[andre@rpi-server ~]$ yaourt -S php-apache 

And add it to the apache main configuration file again: we need to load the library, and include the configuration file:

LoadModule php5_module modules/libphp5.so
Include conf/extra/php5_module.conf

We also have to add something for the gitweb configuration to the config file

<Directory "/srv/http/gitweb">
   DirectoryIndex gitweb.cgi
   Allow from all
   AllowOverride all
   Order allow,deny
   Options ExecCGI
   <Files gitweb.cgi>
   SetHandler cgi-script
   </Files>
   SetEnv  GITWEB_CONFIG  /etc/conf.d/gitweb.conf
</Directory>

To finish the configuration, we're going to add an actual virtual host to the config, which also serves the gitweb. So we're going to edit the vhosts config again:

<VirtualHost *:80>
    ServerName ehv.blaatschaap.be
    Alias /gitweb "/srv/http/gitweb" 
    DocumentRoot /srv/http/blaatschaap.be/ehv
    ErrorLog "/var/log/httpd/blaatschaap.be-ehv-error_log"
    CustomLog "/var/log/httpd/blaatschaap.be-ehv-access_log" combined
    <Directory /var/www/gitweb>
       Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch
       AllowOverride All
       order allow,deny
       Allow from all
       AddHandler cgi-script cgi
       DirectoryIndex gitweb.cgi
   </Directory>
</VirtualHost>

Now, this part of the server is configured. What still has to be done is putting the backup repository so far on the Pi server, and adjusting the script on the ovh server to make backups to this server.

Also, pretty soon I will be getting a new OVH server, as they're offering much better specs for the same price, and I am going to convert to Debian for a server. ArchLinux is great for desktops, but the changed in a rolling distribution such as ArchLinux are not convinient for a machine that's supposed to be always up. Especially the transition from sysvinit to systemd is giving me a headache, as sysvinitscripts are no longer supported... and I am a bit uncomfortable about chaging stuff in the boot loader as I don't have any serial console or anything. If it reboots, I just have to wait till it comes up, if it doesn't.... bad luck.

Besides, I am hosting a few sites for third parties. In order to keep overview, and offer my users a convenient interface I am considering usingISPconfig on my new server. As I have paid for the current server till 15 April, I should have finished the transition by then. I have paid till April since I have renewed my contract just one day before the VAT was increased from 19% to 21%. Anyhow. I plan to order the new server in February, so I have plenty of time for testing.