¡Hola, muy buenas!
Ante todo, me disculpo por la prolongada ausencia de
publicaciones, debido a complicaciones personales, Rolo y yo no pudimos
escribir durante este tiempo. Me agrada informar que, por mi parte, puede
resolver dichas complicaciones y estaré publicando contenido de forma más
seguida.
No me enrollo más. En esta ocasión les vengo a compartir una
experiencia personal que tuve, y de la cual pensé: Oye, que va, que
podría ser una buena entrada pa'l blog.
Hace unos días un amigo me pidió si podía realizar un pentest
sencillo para constatar si su VPS tenía fallos de seguridad, mediante los
cuales puedan tomar control de su servidor de juego. Mi respuesta fue
afirmativa, al fin de cuentas es un amigo, y toda práctica es buena.
¿Qué es Open Game Panel?
De ahora en más OGP, es un panel de control diseñado para
controlar servidores de juego y voz a través de una interfaz web, sin necesidad
de ejecutar comandos.
Realizando un poco de investigación, puede notar que para
realizar la instalación de OGP hacen falta dos partes: Panel y Agent.
·
El panel es la interfaz web, el panel de control
en sí. Contiene el código backend y frontend.
·
El agent o agente es el "controlador",
es la parte que controla las acciones realizadas desde el panel. Según la Wiki
de OGP, es posible instalar ambas partes en un mismo VPS, pero no es
recomendable.
Desde el mismo panel tenemos diversas opciones para
interactuar con nuestros servidores, desde un lector de logs hasta un cliente
FTP incorporado. Todo proceso que se ejecuta a través del panel, corre bajo un
usuario llamado ogpagent, y el mismo tiene permisos de sudo.
El panel no te deja ingresar comandos de ningún tipo, y dado
a que estaba ejecutando la última versión, no había vulnerabilidades conocidas.
Mi amigo estaba ejecutando un servidor de un juego llamado San Andreas
Multiplayer. Dicho juego se trata de una modificación multijugador del
famoso juego de Rockstar Games, Grand Theft Auto: San Andreas.
Investigando sobre dicho juego, averigüé que los servidores
corren bajo "gamemodes" o modos de juego, que son programados bajo un
lenguaje de scripting llamado Pawn. A esto se le suma la posibilidad de añadir
plugins, desarrollados en algún lenguaje de programación, usualmente C++,
Si el mismo juego nos da la posibilidad de ejecutar un
código nuestro, todo se resume a una simple tarea: Un plugin que nos permita
ejecutar comandos del sistema, a través de la instrucción system() de C++.
Para suerte y comodidad del Nobody vago, ya existe un plugin desarrollado
con las características que requería, era cuestión de subirlo a través del
panel y ejecutar.
Me dispuse a programar un pequeño gamemode o filterscript,
utilizando la librería recién descargada.
Con el plugin cargado y el código ejecutado, era cuestión de
ingresar al juego y ejecutar una reverse shell con netcat.
¡Eureka! La reverse shell se había
ejecutado, y ya disponía de una sesión por consola para ejecutar comandos.
Mediante el módulo pty de Python, logré ejecutar una shell
interactiva, la cual me permitía ejecutar comandos como “sudo su”.
Para el interesado, el comando de Python que utilicé fue el
siguiente:
python -c 'import pty; pty.spawn("/bin/bash")'
Investigando un poco más sobre OGP, encontré una carpeta
donde posiblemente se guardaban archivos de configuración, la ruta era /usr/share/ogp_agent/Cfg.
Dentro de dicha carpeta, se encontraba un archivo con el
nombre “Config.pm”, y su contenido era el siguiente:
¿sudo_password? ¿Realmente OGP guardaba una
contraseña de un usuario con permisos sudo en texto plano? Para mi suerte y de
poca fortuna para el resto, esto era afirmativo. Pude loguearme como root
utilizando el usuario con los permisos de sudo.
En cierto punto de mi investigación, podría concluir en que
realmente el servicio era vulnerable, ya que, vamos, logré obtener acceso root.
Pero aún sentía que me faltaba algo, ya que si pude conseguir acceso root tan
fácilmente, seguramente había más información que extraer (obviamente, en texto
plano jeje).
Dentro del panel, existía un archivo de configuración (/var/www/html/includes/config.inc.php), con
credenciales de acceso para una cuenta MySQL no privilegiada. Para resumir,
puedo decir que OGP almacena la contraseña del usuario root de MySQL en texto
plano, dentro de la base de datos accesible por el usuario no privilegiado.
Aunque ya teniendo acceso root al VPS, esto no me servía de mucho.
¿Sería posible acceder a más información? Recordé que aún me
faltaba por investigar el servidor de San Andreas Multiplayer de mi amigo.
Antes de seguir quiero hacer un alto, ya que la siguiente
parte de la publicación va más allá de las “vulnerabilidades” de OGP, ya que esto
era posible realizarse sin acceso root al VPS, y solo contando con acceso al
usuario OGP correspondiente. Aún así, me parecía prudente escribir sobre esto,
ya que demostraré que es posible acceder a “más”.
El servidor de mi amigo contaba con un plugin de MySQL, y
una base de datos en un servidor remoto. Los datos de conexión MySQL estaban embebidos
o hardcodeados dentro del código de la gamemode, del cual yo no disponía. Cabe
destacar que esa información tampoco era visible, a simple vista, desensamblando
el compilado de la gamemode o extrayendo la lista de strings de la misma.
Pensé en que era posible sniffear el tráfico utilizando
tshark, pero luego iba a tener que romper la contraseña hasheada de todas
formas, no era lo más recomendable.
Esta es la parte de la historia donde se me iluminó mi
cabecita y saqué mi programador interior: El plugin de MySQL era de código
abierto, simplemente tenia que modificarlo y hacer que guarde un registro de
los datos de conexión. Averigüé que la versión del plugin ejecutada era la R39-6,
un tanto vieja para la fecha, pero aún así el código se encuentra disponible en GitHub.
Encontré que la función de conexión se encontraba en el
archivo CScripting.cpp, y ya disponía de una función de “log” de
depuración, el cuál guardaba el host, usuario y base de datos, pero no la
contraseña (por lógicas razones).
Editando levemente el código, reemplazando los asteriscos
por el format specifier correspondiente, logré que él registro de depuración de
MySQL muestre la contraseña en texto plano.
Nota: Existe una función dentro del plugin la cual
permite desactivar todos los registros, o al menos el de depuración. Es posible
ignorar dicha función, simplemente forzando LOG_DEBUG desde el código, esto se
encuentra en el archivo CLog.h).
Ya con los datos de acceso MySQL, mi trabajo había
finalizado: Había logrado ingresar a una base de datos externa al VPS. Pero,
¿qué secretos guardaba la base de datos?
La misma incluía tablas personalizadas sobre el servidor del
juego, pero además contenía las tablas de un foro SMF. Recordemos que
mediante el acceso al panel administrativo de SMF, podemos subir un backdoor
PHP utilizando la función de “modificaciones” o “editar tema”.
Es precisamente lo que hice, y ahora sí, mi trabajo había
terminado: Había conseguido acceso root a un VPS y acceso a un Webhost ajeno a
dicho VPS.
Espero que esta publicación haya sido informativa, y me
disculpo por la carencia de redacción. Espero haber sido suficientemente claro
explicando los conceptos sobre esta “vulnerabilidad”.
También cabe destacar que no se trata de una vulnerabilidad
en sí, simplemente es una forma incorrecta de guardar una contraseña.
¡Saludos desde el más allá!
Nobody.
Nobody.
¡Pssst! Os recuerdo que también podéis seguirme en Twitter :-).