Instalar MongoDB y PHP en Ubuntu 16.04

En este artículo veremos cómo instalar la base de datos NoSQL MongoDB 3.4, la configuración inicial básica de seguridad que hay que hacer y la instalación del soporte de MongoDB para PHP 7, todo ello sobre Ubuntu 16.04. Este artículo servirá de base para uno posterior en el que realizaremos algunos ataques de inyección "de libro" sobre este gestor.

Para realizar la instalación inicial me baso en el siguiente procedimiento y posteriormente en la documentación oficial de mongodb.

1. Instalación inicial de MongoDB

La versión de MongoDB que viene en la distribución (la 2.6) está fuera de soporte del fabricante, por ello realizaremos la instalación de la última versión estable utilizando los repositorios oficiales de MongoDB.

En general soy enemigo de usar directamente repositorios PPA, si tuviéramos muchas máquinas con esta instalación convendría crear nuestro propio repositorio y migrar los paquetes del PPA al nuestro.
Agrego las keys
root@mongodb:~# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
Executing: /tmp/tmp.PAVRA2r96X/gpg.1.sh --keyserver
hkp://keyserver.ubuntu.com:80
--recv
0C49F3730359A14518585931BC711F9BA15703C6
gpg: solicitando clave A15703C6 de hkp servidor keyserver.ubuntu.com
gpg: clave A15703C6: clave pública "MongoDB 3.4 Release Signing Key <packaging@mongodb.com>" importada
gpg: Cantidad total procesada: 1
gpg:               importadas: 1  (RSA: 1)
Agrego el repositorio fuente y lo instalo
root@mongodb:~# echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" >/etc/apt/sources.list.d/mongodb-org-3.4.list
root@mongodb:~# apt-get update && apt-get install mongodb-org
    ....
Añadiendo el usuario del sistema `mongodb' (UID 111) ...
Añadiendo un nuevo usuario `mongodb' (UID 111) con grupo `nogroup' ...
No se crea el directorio personal `/home/mongodb'.
Añadiendo el grupo `mongodb' (GID 117) ...
Hecho.
Añadiendo al usuario `mongodb' al grupo `mongodb' ...
Adding user mongodb to group mongodb
Hecho.
Configurando mongodb-org-mongos (3.4.10) ...
Configurando mongodb-org-tools (3.4.10) ...
Configurando mongodb-org (3.4.10) ...
Habilitamos e iniciamos el servicio
root@mongodb:~# systemctl enable mongod
Created symlink from /etc/systemd/system/multi-user.target.wants/mongod.service to /lib/systemd/system/mongod.service.
root@mongodb:~# systemctl start mongod

2. Configuración de usuario administrador en MongoDB

Con esto ya está instalado, pero por defecto cualquier proceso que se ejecute en el la máquina tendrá acceso completo al gestor de base de datos mediante el socket tcp. Esto es un grave problema de seguridad (en las primeras versiones se escuchaba en todas las interfaces). Por ello crearemos un usuario administrador y habilitaremos la autenticación.

Sustituye el nombre de tu usuario administrador y tu password.
Creamos el usuario admin en mongo
luisadm@mongodb:~$ mongo
MongoDB shell version v3.4.10
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.10
Welcome to the MongoDB shell.
> use admin
switched to db admin
> db.createUser(
...   {
...     user: "luisadm",
...     pwd: "12345",
...     roles: [ { role: "userAdminAnyDatabase", db: "admin"} ]
...   }
... )
Successfully added user: {
	"user" : "luisadm",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	]
}
> quit()
Habilitamos la autenticación editando /etc/mongodb.conf
security:
  authorization: "enabled"
Reiniciamos el servicio
root@mongodb:~# systemctl restart mongod
Comprobamos que funciona conectándonos como administradores
luisadm@mongodb:~$ mongo -u luisadm -p --authenticationDatabase admin
MongoDB shell version v3.4.10
Enter password:
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.10
> show dbs
admin  0.000GB
local  0.000GB

3. Instalación de PHP con soporte de MongoDB

Ya tenemos la base de datos configurada con un usuario administrador. Ahora tenemos que instalar el servidor web, el entorno PHP y las librerías necesarias para conectarnos a la base de datos.

Soy enemigo de instalar cosas "a pelo", la instalación vía pecl está automatizada pero se encuentra fuera del sistema de paquetería. Por ello, en servidores en producción convendría crear el paquete deb en una máquina de desarrollo y utilizar nuestro repositorio.
Instalamos apache + php + dependencias compilación
root@mongodb:~# apt-get install libapache2-mod-php
root@mongodb:~# apt-get install php-dev pkg-config php-pear unzip composer
Instalamos los bindings de mongo usando pecl
root@mongodb:~# pecl install mongodb
downloading mongodb-1.3.4.tgz ...
Starting to download mongodb-1.3.4.tgz (848,798 bytes)
......done: 848,798 bytes
412 source files, building
running: phpize
Configuring for:
PHP Api Version:         20151012
Zend Module Api No:      20151012
Zend Extension Api No:   320151012
      .....
Build process completed successfully
Installing '/usr/lib/php/20151012/mongodb.so'
install ok: channel://pecl.php.net/mongodb-1.3.4
configuration option "php_ini" is not set to php.ini location
You should add "extension=mongodb.so" to php.ini
Habilitamos la extensión en apache y en cli
root@mongodb:~# echo "extension=mongodb.so" > /etc/php/7.0/mods-available/mongodb.ini
root@mongodb:~# cd /etc/php/7.0/apache2/conf.d/
root@mongodb:/etc/php/7.0/apache2/conf.d# ln -s /etc/php/7.0/mods-available/mongodb.ini 20-mongodb.ini
root@mongodb:/etc/php/7.0/apache2/conf.d# cd /etc/php/7.0/cli/conf.d/
root@mongodb:/etc/php/7.0/cli/conf.d# ln -s /etc/php/7.0/mods-available/mongodb.ini 20-mongodb.ini
root@mongodb:/etc/php/7.0/cli/conf.d# systemctl restart apache2

Ya tenemos el intérprete de php y los bindings a mongo. Sin embargo, estos bindings no son utilizados directamente, en su lugar se ha de utilizar un wrapper en PHP que proporciona una API soportada oficialmente por el fabricante. Para su utilización, vamos a instalar esta API en la carpeta en la que vamos a desarrollar la aplicación. Para ello:

Instalando API PHP de mongo
root@mongodb:~# mkdir -p /var/www/html/mongodb
root@mongodb:~# chown luisadm /var/www/html/mongodb/
root@mongodb:~# exit
luisadm@mongodb:~$ cd /var/www/html/mongodb/
luisadm@mongodb:/var/www/html/mongodb$ composer require mongodb/mongodb
Using version ^1.2 for mongodb/mongodb
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing mongodb/mongodb (1.2.0)
    Downloading: 100%

Writing lock file
Generating autoload files

Para comprobar que funciona simplemente crearemos un index.php que la incluya.

Contenido de un index.php de prueba
<?php

// incluyemos la librería composer
require 'vendor/autoload.php';

$cliente = new MongoDB\Client("mongodb://localhost");

echo "Instancia correctamente un objeto de la clase!";

Navegamos y si vemos la frase "Instancia correctamente…​" es que todo está ok.

Hasta aquí es todo por hoy, ya tenemos un servidor con apache+php+mongodb listo. En un artículo posterior veremos algunos ataques de inyección que pueden realizarse sobre este gestor. Mientras tanto…​ no te olvides de compartir si te ha sido de utilidad ;)