He visto un par de temas similares, pero se refieren a no citar variables, lo que sé que podría conducir a resultados no deseados.
Vi este código y me preguntaba si sería posible inyectar algo para ejecutar cuando se ejecuta esta línea de código:
echo run after_bundle
Respuestas:
Para el caso específico
No es necesario citar. No es necesario citar porque el argumento
echo
es cadenas estáticas que no contienen expansiones variables o sustituciones de comandos, etc. Son "solo dos palabras" (y, como señala Stéphane , se construyen adicionalmente a partir del conjunto de caracteres portátil ).El "peligro" viene cuando manejas datos variables que el shell puede expandir o interpretar. En tales casos, se debe tener cuidado de que el shell haga lo correcto y que el resultado sea lo que se pretende.
Las siguientes dos preguntas contienen información relevante al respecto:
echo
a veces se usa para "proteger" comandos potencialmente dañinos en las respuestas de este sitio. Por ejemplo, puedo mostrar cómo eliminar archivos o mover archivos a un nuevo destino usandoo
Esto generaría comandos en el terminal en lugar de eliminar o cambiar el nombre de los archivos. El usuario podría inspeccionar los comandos, decidir que se ven bien, eliminarlos
echo
y volver a ejecutarlos.Su comando
echo run after_bundle
puede ser una instrucción para el usuario, o puede ser un código "comentado" que es demasiado peligroso para ejecutar sin saber las consecuencias.Usando
echo
esto, uno tiene que saber qué hace el comando modificado y uno debe garantizar que el comando modificado realmente sea seguro (potencialmente no lo sería si contuviera redirecciones, y usarlo en una tubería no funciona, etc.)fuente
echo rm "first file.txt" "second file.txt"
es de ninguna manera diferenteecho rm "first" "file.txt" "second" "file.txt"
, la salida de ambos es la misma. Si desea generar un comando de shell como salida, debe usarprintf '%q ' rm "first file.txt" "second file.txt"; echo
o algo equivalente que vuelva a generar citas sintácticas que se evalúen comoargv
aprobadas.sh
no es exactamente un patrón poco común, y ver a la gente preguntar "¿por quéfoo
funciona cuando lo ejecuto en una línea de comando, pero este script que emite esa cadena exactaecho
en frente de la línea no lo hace? " sucede todo el tiempo aquí. Más aún, la salida de depuración no es útil si oculta sus errores, y si sus errores están relacionados con citas, entoncesecho
no los revelará.Solo una nota adicional sobre la excelente respuesta de @ Kusalananda .
está bien porque ninguno de los caracteres en esos 3 argumentos¹ pasados para
echo
contener caracteres que son especiales para el shell.Y (el punto extra que quiero destacar aquí) no hay una configuración regional del sistema donde esos bytes puedan traducirse a caracteres que sean especiales para el shell.
Todos esos caracteres están en lo que POSIX llama el juego de caracteres portátil . Esos caracteres deben estar presentes y codificados de la misma manera en todos los juegos de caracteres en un sistema POSIX².
De modo que esa línea de comando se interpretará de la misma forma independientemente de la configuración regional.
Ahora, si comenzamos a usar caracteres fuera de ese conjunto de caracteres portátil, es una buena idea citarlos incluso si no son especiales para el shell, porque en otro entorno local, los bytes que los constituyen pueden interpretarse como caracteres diferentes que podrían convertirse en especial a la concha. Tenga en cuenta que es si está utilizando
echo
o cualquier otro comando, el problema no esecho
con la forma en que el shell analiza su código.Por ejemplo en un UTF-8:
Eso
à
está codificado como 0xc3 0xa0. Ahora, si tiene esa línea de código en una secuencia de comandos de shell y la secuencia de comandos de shell es invocada por un usuario que utiliza una configuración regional cuyo conjunto de caracteres no es UTF-8, esos dos bytes podrían tener caracteres muy diferentes.Por ejemplo, en un
fr_FR.ISO8859-15
entorno local, un entorno local típico francés que utiliza el juego de caracteres estándar de un solo byte que cubre el idioma francés (el mismo que se usa para la mayoría de los idiomas de Europa occidental, incluido el inglés), ese byte 0xc3 se interpreta como elÃ
carácter y 0xa0 como el no Rompiendo el carácter del espacio.Y en algunos sistemas como NetBSD³, ese espacio que no se rompe se considera como un carácter en blanco (
isblank()
en él devuelve verdadero, coincide con[[:blank:]]
) y los shells como,bash
por lo tanto, lo tratan como un delimitador de token en su sintaxis.Esto significa que en lugar de correr
echo
con$'voil\xc3\xa0'
como argumento, se ejecutan con$'voil\xc3'
como argumento, lo que significa que no se imprimirávoilà
correctamente.Se pone mucho peor con los juegos de caracteres chinos como Big5, Big5-HKSCS, GB18030, GBK que tienen muchos personajes cuya codificación contiene la misma codificación que el
|
,`
,\
(por nombrar el peor) (también que SJIS ridícula, también conocido como Microsoft kanji, excepto que es en¥
lugar de\
, pero aún así es tratado\
por la mayoría de las herramientas ya que está codificado como 0x5c allí).Por ejemplo, si está en un
zh_CN.gb18030
entorno chino, escribe un script como:Ese script se generará
詜 reboot
en un entorno local utilizando GB18030 o GBK,唰 reboot
en un entorno local utilizando BIG5 o BIG5-HKSCS, pero en un entorno local C utilizando ASCII o un entorno local utilizando ISO8859-15 o UTF-8, sereboot
ejecutará porque la codificación GB18030 de詜
es 0xd4 0x7c y 0x7c es la codificación de|
ASCII, por lo que terminamos ejecutando:(que representa sin embargo el byte 0xd4 se representa en la configuración regional). Ejemplo usando el menos dañino en
uname
lugar dereboot
:(
uname
Se corrió).Por lo tanto, mi consejo sería citar todas las cadenas que contienen caracteres fuera del conjunto de caracteres portátil.
Sin embargo, tenga en cuenta que, dado que la codificación de
\
y`
se encuentra en la codificación de algunos de esos caracteres, es mejor no usar\
o"..."
o$'...'
(dentro de los cuales`
y / o\
todavía son especiales), sino'...'
citar caracteres fuera del conjunto de caracteres portátil.No conozco ningún sistema que tenga una configuración regional donde el juego de caracteres tenga algún carácter (aparte de
'
sí mismo, por supuesto) cuya codificación contenga la codificación'
, por lo'...'
que definitivamente debería ser el más seguro.Tenga en cuenta que varios shells también admiten una
$'\uXXXX'
notación para expresar caracteres en función de su punto de código Unicode. En shells comozsh
ybash
, el carácter se inserta codificado en el juego de caracteres de la configuración regional (aunque puede causar comportamientos inesperados si ese juego de caracteres no tiene ese carácter). Eso le permite evitar insertar caracteres no ASCII en su código de shell.Así arriba:
O:
(con la advertencia, podría romper el script cuando se ejecuta en entornos locales que no tienen esos caracteres).
O mejor, ya
\
que también es especial paraecho
(o al menos algunasecho
implementaciones, al menos las que cumplen con Unix):(tenga en cuenta que
\
también es especial en el primer argumentoprintf
, por lo que también es mejor evitar los caracteres no ASCII en caso de que puedan contener la codificación de\
).Tenga en cuenta que también puede hacer:
(eso sería excesivo, pero podría darte un poco de tranquilidad si no estás seguro de qué personajes están en el conjunto de caracteres portátil)
Además, asegúrese de nunca usar la antigua
`...`
forma de sustitución de comandos (que introduce otro nivel de procesamiento de barra invertida), pero en su$(...)
lugar use .¹ técnicamente,
echo
también se pasa como argumento a laecho
utilidad (a decirle cómo se invoca), que es elargv[0]
yargc
es 3, aunque en la mayoría de las conchas hoy en díaecho
se orden interna, de manera queexec()
de un/bin/echo
archivo con una lista de 3 argumentos es simulado por el cáscara. También es común considerar que la lista de argumentos comienza con el segundo (argv[1]
toargv[argc - 1]
), ya que es sobre los que actúan principalmente los comandos.² ¡una notable excepción a que es la ridícula
ja_JP.SJIS
localización de los sistemas FreeBSD cuyo juego de caracteres no tiene\
ni~
carácter!³ tenga en cuenta que si bien muchos sistemas (FreeBSD, Solaris, no GNU) consideran U + 00A0 como
[[:blank:]]
en configuraciones regionales UTF-8, pocos lo hacen en otras configuraciones regionales como las que usan ISO8859-15, posiblemente para evitar este tipo de problema.fuente
echo
...", solo cuento 2 argumentos pasados al comandoecho
, los argumentos que puedo contar sonrun
yafter_bundle
, me gustaría explicar cómo contado y llegó a 3 argumentos?echo
). Vea(exec -a foo /bin/echo --help)
en un sistema GNU y con el shell GNU cómo pasar un primer argumento arbitrario a la/bin/echo
utilidad.$0
parámetros posicionales en conchas.iconv
en las queESC
se convierte'
. Prueba (como ejemplo):printf '\x1b'|iconv -f utf8 -t IBM-937|xxd
'
. Tratarprintf '\u2804' | iconv -f utf8 -t BRF | xxd
. Hay codificaciones en las que hay muchos puntos de código que se convierten'
. Alrededor de 8695 puntos de código en UCS-4 se convierten'
. Tratarprintf '\U627' | iconv -cf utf-8 -t UCS-4
. Varias (37) codificaciones convierten el carácter 0x127 en a'
. Probarprintf '\U127' | iconv -cf utf8 -t UCS2 |xxd