$ k=v p &
[1] 3028
¿Hay alguna forma de p
cambiar el contenido de /proc/3028/environ
no mencionar k=v
mientras p
todavía se está ejecutando?
linux
security
process
linux-kernel
environment-variables
Cetin Sert
fuente
fuente
Respuestas:
En Linux, puede sobrescribir el valor de las cadenas de entorno en la pila.
Para que pueda ocultar la entrada sobrescribiéndola con ceros o cualquier otra cosa:
Correr como:
el
k=v
ha sido sobrescrito con\0\0\0
.Tenga en cuenta que
setenv("k", "", 1)
para sobrescribir el valor no funcionará, ya que en ese caso,"k="
se asigna una nueva cadena.Si no ha modificado la
k
variable de entorno consetenv()
/putenv()
, entonces también debería poder hacer algo como esto para obtener la dirección de lak=v
cadena en la pila (bueno, de una de ellas):Sin embargo, tenga en cuenta que solo elimina una de las
k=v
entradas recibidas en el entorno. Por lo general, solo hay uno, pero nada impide que nadie pase los dosk=v1
yk=v2
(ok=v
dos veces) en la lista env enviada aexecve()
. Esa ha sido la causa de vulnerabilidades de seguridad en el pasado, como CVE-2016-2381 . Realmente podría sucederbash
antes del shellshock al exportar tanto una variable como una función con el mismo nombre.En cualquier caso, siempre habrá una pequeña ventana durante la cual la cadena var var aún no se ha anulado, por lo que es posible que desee encontrar otra forma de pasar la información secreta al comando (como una tubería, por ejemplo) si la expone a través de
/proc/pid/environ
Es una preocupación.También tenga en cuenta que
/proc/pid/cmdline
, al contrario ,/proc/pid/environment
solo es accesible por procesos con el mismo euid o raíz (o root solo si el euid y el ruid del proceso no son lo mismo que parece).Puede ocultarles ese valor
/proc/pid/environ
, pero aún así pueden obtener cualquier otra copia que haya hecho de la cadena en la memoria, por ejemplo, adjuntando un depurador.Consulte https://www.kernel.org/doc/Documentation/security/Yama.txt para ver formas de evitar que al menos los usuarios no root lo hagan.
fuente
No ha sido necesario sobrescribir las cadenas anteriores (no realmente en ) la pila del hilo principal en Linux desde 2010.
Ambos
/proc/self/cmdline
y/proc/self/environ
son modificables por el propio proceso en tiempo de ejecución, a fuerza de llamar a laprctl()
función conPR_SET_MM_ARG_START
+PR_SET_MM_ARG_END
oPR_SET_MM_ENV_START
+ respectivamentePR_SET_MM_ENV_END
. Estos establecen directamente los punteros de memoria en el espacio de memoria de la aplicación del proceso, retenido por el núcleo para cada proceso, que se utilizan para recuperar el contenido de/proc/${PID}/cmdline
y/proc/${PID}/environ
, y por lo tanto, la línea de comandos y el entorno informados por elps
comando.Entonces, uno simplemente necesita construir un nuevo argumento o cadena de entorno (no vector, aviso: la memoria apuntada debe ser los datos de la cadena real, concatenados y
␀
delimitados) y decirle al núcleo dónde está.Esto está documentado en la página del manual de Linux para la
prctl(2)
función, así como en laenviron(7)
página del manual. Lo que no está documentado es que el núcleo rechaza cualquier intento de establecer la dirección de inicio por encima de la dirección de finalización, o la dirección de finalización por debajo de la dirección de inicio; o para (re) establecer cualquiera de las direcciones a cero. Además, este no es el mecanismo original propuesto por Bryan Donlan en 2009, que permitió establecer el inicio y el final en una sola operación, atómicamente. Además, el núcleo no proporciona ninguna forma de obtener los valores actuales de estos punteros.Esto dificulta modificar el entorno y las áreas de línea de comando con
prctl()
. Uno tiene que llamar a laprctl()
función hasta cuatro veces porque los primeros intentos pueden dar lugar a intentos de establecer el puntero de inicio más alto que el puntero de finalización, dependiendo de dónde estén los datos antiguos y nuevos en la memoria. Uno tiene que llamar a más de cuatro veces si uno quiere asegurarse de que esto no se traduce en una ventana de oportunidad para otros procesos en el sistema para inspeccionar cualquier rango del proceso de espacio de memoria en el período en que el comienzo nuevo / fin se ha establecido pero el nuevo final / inicio no se ha establecido.Una sola llamada al sistema atómico que establece todo el rango de una sola vez hubiera sido mucho más fácil para los programas de aplicaciones de usar de forma segura.
Una arruga adicional es que, sin una razón realmente buena (dadas las comprobaciones en el núcleo, la sobreescritura de las áreas de datos originales de todos modos , y el hecho de que los equivalentes no son operaciones privilegiadas en ninguno de los BSD), en Linux esto requiere superusuario privilegios
Escribí bastante simple
setprocargv()
ysetprocenvv()
funciones para mis conjuntos de herramientas, que emplean esto. Los programas de carga en cadena de los conjuntos de herramientas que están integrados, comosetenv
yforeground
, por lo tanto, reflejan los argumentos de comando encadenados y el entorno, donde Linux lo permite.Tenga en cuenta que esto no interfiere con las cosas que rastrean el proceso y acceden a su memoria directamente por otros medios (en lugar de a través de estos dos pseudo archivos), y por supuesto deja una ventana antes de que se modifiquen las cadenas donde se puede ver esta información, solo como sobrescribe los datos sobre la pila del hilo principal. Y tal como es el caso con la sobrescritura de los datos, esto no tiene en cuenta las bibliotecas de tiempo de ejecución de lenguaje que hacen copias del entorno (en el montón) en varias circunstancias. En general, no considere que este es un mecanismo tan bueno para pasar "secretos" a un programa como (por ejemplo) que herede un descriptor de archivo abierto al extremo de lectura de una tubería sin nombre, lea en un búfer de entrada totalmente bajo su control que luego limpie.
Otras lecturas
fuente
/proc/$pid/stat
(además de otros valores que pueda necesitar enstruct prctl_mm_map
). Vea también mi ejemplo filter_env.c para una pequeña demostración. JdeBP, ¿puedes agregar enlaces a tussetprocargv()
/setprocenvv()
funciones?