- ENTRADA 040 -
Verificando PKGBUILDs
Cuidado con Morris y Lona Cohen, no son de fiar, regístrelos antes de tratar con ellos, son muy peligrosos
--- Fecha: lun 01 abr 2024 18:29:22 CEST ---
Tras lo ocurrido con la vulnerabilidad consistente en la introducción de una puerta trasera o backdoor en el paquete xz, asaltan las dudas sobre la seguridad de nuestros equipos y nos volvemos un poco paranoides. Luego, poco a poco, se pasa, y volvemos a la "normalidad"... ¿seguro?
Archlinux tiene sus paquetes oficiales, y luego tiene un repositorio de paquetes creados y/o mantenidos por la comunidad, los llamados AUR (Archlinux User Repository).
Siempre se recomienda intentar no instalar desde AUR porque al no ser los repositorios oficiales no se puede garantizar su seguridad, pero la verdad es que hay mucho buen softaware y reconocido de sobras en AUR, sea porque no ha entrado en los repositorios oficiales, o porque fueron trasladados a AUR, o por la razón que sea, y no queda otro remedio que instalarlos.
Un poco de teoría
AUR funciona descargando un archivo llamado PKGBUILD, que no es más que un bashscript que contiene la información de compilación requerida por los paquetes de Arch Linux y que el comando makepkg utilizará para su compilación, siguiendo las instrucciones de ese PKGBUILD.
En este PKAGBUILD no solo aparecen las órdenes internas, si no también órdenes externas, como la descarga de dependencias o adquirir los archivos necesarios para crear el paquete (tipo pkgname.pkg.tar.zst). Una vez compilado, obtienes un binario que ya se instala como si lo hicieras con el pacman oficial. ¿Ves donde está el riesgo?
PKGUILD le va a decir al sistema qué tiene que hacer, a qué URLs ha de conectarse y qué paquetes necesarios descargará de esa URL, y aunque es un proceso asistido por consola y con cierta intervención por parte del usuario/a/e, no es del todo transparente.
Así que yo SIEMPRE reviso el PKGBUILD para ver qué va a hacer.
Si, vale, es un script muy básico, y además podrías decir que las URLs a las que conecta pueden ser necesarias, incluso de confianza, pero que esos archivos que descarga, que forman parte del código del futuro binario, podrían ser inseguros. Cierto, para ser paranoico nivel Pro, debería mirar el código de todo lo que PKGBUILD descarga (siempre es en código fuente), pero hay 2 problemas:
- A veces hay decenas de archivos con muchísimas líneas de código, ¿me voy a tirar varios días revisando código para instalar un programa que necesito ahora?
- ¿Mis conocimientos de programación abarcan tanto?, no, de hecho, no sé programar, así que....
Si, esto puede ser peligroso, de ahí a que no se recomiende instalar desde AUR si no queda otro remedio, pero revisando los PKGBUILDs filtras gran parte de posibles modificaciones maliciosas, así que si no queda otro remedio, recomiendo revisarlos antes de instalar.
Un PKGBUILD por dentro
Un PKGBUILD es muy sencillo. Consta de variables, de las que hay varias que son de uso obligado para que no de error al compilar, ya se ha hecho así para que puedas revisar qué va a hacer y a donde va a apuntar sus conexiones. Las variables obligatorias son:
- pkgname, pkgver, pkgrel y arch.
NOTA: La variable "license" no es estrictamente necesaria para construir un paquete, pero se recomienda para cualquier PKGBUILD compartido con otros, ya que makepkg generará una advertencia si no está presente.
NOTA 2: Al final del artículo dejo un PKGBUILD de ejemplo
Variables o matrices
pkgname
Es el nombre de paquete, ya sea único o para paquetes divididos en matriz de nombres. pkgname debe coincidir con el nombre del tarball fuente del software, y aunque no es obligatorio, desconfía si es diferente.
pkgname=foo pkgname=('foo' 'bar').
pkgver
Es la versión del paquete y debe ser la misma que la versión publicada por el autor del software original (desconfía si no es así).
pkgver=5.13
pkgrel
Es el número de lanzamiento, conocida como versión menor, que permite diferenciar entre compilaciones consecutivas de la misma versión de un paquete. Como a cada lanzamiento de la misma versión hay que incrementar en 1, desconfía si de repente este valor sube demasiado. Cuando se lanza una nueva versión del software, este valor debe ser restablecido a 1.
arch
Es la arquitectura donde se va a construir el binario, aunque oficialmente pacman solo admite x86_64, otros proyectos pueden admitir otras arquitecturas, como ARM. Aquí podrás encontrar 2 valores posibles:
- arch=('any') Se compila en cualquier arquitectura y su binario es independiente de la arquitectura en su estado compilado.
- arch=('x86_64') Se compila en cualquier arquitecturas pero su binario solo es compatible para X64.
Una vez vistas las variables obligatorias, existen otras que aunque no lo son, dependiendo de la naturaleza del paquete, serán necesarias:
pkgbase
Su valor suele ser el mismo que pkgname, y se usa para construir paquetes divididos, para referirse al grupo de paquetes para makepkg, por ejemplo, Xorg.
epoch
Se utiliza para forzar que el paquete se vea como más nuevo que cualquier versión anterior con una época anterior porque cambia el esquema de numeración de versiones de un paquete rompiendo la lógica normal de comparación de versiones. Por ejemplo 1:5.13-2:
pkgver=5.13 pkgrel=2 epoch=1
NOTA: epoch solo debe utilizarse cuando sea absolutamente necesario.
pkgdesc
Una pequeña descripción del paquete de menos de 80 carácteres y que no debe incluir el nombre del paquete como autorreferencia (desconfía si es así)
url
La URL del sitio oficial del software que se empaqueta.
license
La licencia bajo la cual se distribuye el software, que debe apuntar a alguna del directorio /usr/share/licenses/common (desconfía si no la encuentras ahí).
groups
El grupo al que pertenece el paquete. Por ejemplo, al instalar plasma, instala todos los paquetes que pertenecen a ese grupo.
depends
Son las dependencias necesarias para que el programa funcione o se compile. Las dependencias definidas dentro de la función package() solo son necesarias para ejecutar el software.
Aquí hay que ir con mucho cuidado, ya que si no se declaran bien, el programa no funcionará o lo hará de forma anómala. Si el nombre de la dependencia parece ser una biblioteca, por ejemplo depends=('libfoobar.so'), makepkg intentará encontrar un binario que dependa de la biblioteca en el paquete creado y añadirá la versión que necesita el binario, así que cuidado con las dependencias que va a buscar. En la web de archlinux, cuando buscas un paquete, te indica abajo sus dependencias, así que es una buena guía para comparar.
makedepends
Una matriz de paquetes que solo se requieren para construir el software y luego pueden borrarse. Como el anterior, cuidado lo que pide.
checkdepends
Esta es más rara. Es una matriz de paquetes de los que depende el software para ejecutar su conjunto de pruebas, pero que no son necesarios en tiempo de ejecución. Los paquetes de esta lista siguen el mismo formato que depends.
optdepends
Dependencias opcionales, que pese a no ser necesarios para que el software funcione, proporcionan funciones adicionales. Si no lo ves claro, puedes quitarlas del PKGBUILD
optdepends=('cups: printing support' 'sane: scanners support' 'libgphoto2: digital cameras support' 'alsa-lib: sound support' 'giflib: GIF images support' 'libjpeg: JPEG images support' 'libpng: PNG images support')
provides
Paquetes adicionales cuyas características proporciona el software. Está muy ligado a la siguiente variable "conflicts".
conflicts
Paquetes que entran en conflicto o causan problemas con el paquete y que deberán eliminarse si están instalados. Los conflictos se comprueban con pkgname, así como con los nombres especificados en "provides". Por ejemplo, estos dos paquetes entran en conflicto:
- netbeans proporciona implícitamente netbeans como el pkgname mismo
- netbeans-cpp proporciona netbeans y entra en conflicto con netbeans
source
Archivos necesarios para construir el paquete, que apunta a la ubicación de la fuente del software, que suele ser HTTP o FTP completa. Ojo aquí donde apunta esta variable. Si desconfias de la URL, no sigas instalando.
Los archivos pueden descargarse de un lugar seguro y dejarlos junto con PKGBUILD, ya que antes de que comience el proceso de compilación actual, todos los archivos a los que hace referencia esta variable se descargarán o comprobarán si existen, y makepkg no continuará si falta alguno.
NOTA: Se recomienda adjuntar los archivos de verificación .sig, .sign o .asc de los archivos fuente, ya que son reconocidos por makepkg como firmas PGP y se utilizarán automáticamente para verificar la integridad del archivo fuente correspondiente.
Integridad
Aquí van variables de verificación y los valores siempre deben ser los proporcionados por upstream (desconfia si son diferentes). De mayor seguridad a menor son: b2, sha512, sha384, sha256, sha224, sha1, md5, o ck.
Conclusiones
Todo este tochazo que te he metido puedes pensar que es engorroso y que tardas mucho en hacer las comprobaciones, pero no es así. Quizá al principio seas algo más torpe por la falta de costumbre, pero luego vas como un rayo. Te recomiendo que guardes los enlaces a las principales webs y tengas a mano las herramientas necesarias para agilizar.
Si te preocupa la seguridad de tu equipo, sin duda no puedes dejar de hacer estas verificaciones.
A modo de resumen:
- Verifica concordancia de nombres y versiones
- Verifica URLs
- Verifica dependencias
- Verifica integridades
- Haz una búsqueda de los términos que no conozcas o te resulten sospechosos
- Visita siempre la web oficial de AUR para hacer comparativas de todo lo anterior
Y hasta aquí el artículo de hoy. Puedes encontrar mucha más info en la web oficial de Archlinux:
Ejemplo de PKGBUILD sencillo
## Maintainer: khanhas <xuankhanh963@gmail.com>, itsmeow <itsmeow@itsmeow.dev> pkgname=spicetify-cli pkgver=2.36.2 pkgrel=1 pkgdesc='Command-line tool to customize Spotify client' arch=('x86_64' 'i686') url='https://github.com/spicetify/spicetify-cli' license=('LGPL2.1') makedepends=('go') optdepends=('xdg-utils: Allows for opening directories in default file manager') source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz") sha256sums=('d631ab3e8ac2725922fb686a22ebf6c86bddc55974311cb1d9ee438278670c62') build() { cd "$pkgname-$pkgver" export GO111MODULE="auto" export GOPATH="$srcdir" go build -ldflags="-X 'main.version=$pkgver'" -o spicetify } check() { cd "$pkgname-$pkgver" test "v$(./spicetify -v)" = "v$pkgver" || exit 1 } package() { cd $pkgname-$pkgver install -Dm755 ./spicetify "$pkgdir"/usr/share/$pkgname/spicetify cp -r ./Themes ./Extensions ./CustomApps ./jsHelper ./globals.d.ts ./css-map.json "$pkgdir"/usr/share/$pkgname rm -f ./shortcut echo "#!/bin/sh /usr/share/$pkgname/spicetify \"\$@\"" >> ./shortcut install -Dm755 ./shortcut "$pkgdir"/usr/bin/spicetify # Clean up deps go clean -modcache }
Tags: #AUR #PKGBUILD
/blog/