如何使用纯 unset shell 内置函数?你能编写不受篡改的 shell 脚本吗?

2023-11-22

我的意思是我想用unset这本身不是一个 shell 函数。如果我能做到这一点,我就能确保command因跑步而纯粹

#!/bin/sh
{ \unset -f unalias command [; \unalias unset command [ } 2>/dev/null;
# make zsh find *builtins* with `command` too:
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on

如果我使用 Debian Almquist shell (dash),我想我可以信赖它\unset是纯粹的。至少我无法定义名为的 shell 函数unset in dash。而在bash or in zsh我可以定义unset() { echo fake unset; },此后我无法取消设置该功能:\unset -f unset输出“假未设置”。

与此相关,在bash脚本,可以通过以下方式导出函数export -f <function name>以便它可以用于bash脚本调用的脚本。但是,同样的方法不适用于dash脚本。我想知道,如果我正在使用,我是否必须担心命令被定义为我正在编写的脚本文件之外的 shell 函数dash?其他 POSIX 兼容 shell 怎么样?


注意:除非另有说明,以下内容适用于所有主要的 POSIX 兼容 shell:bash, dash, ksh, and zsh. (dashDebian Almquist Shell 是默认 shell(sh)在基于 Debian 的 Linux 发行版(例如 Ubuntu)上。

  • unset有其本来的意义 - 可以取消定义 shell 的内置函数功能以其-f option- 是个确保任何其他 shell 关键字、命令或内置命令具有其原始含义的关键.

    • 从未修改的开始unset,您可以确保未修改shopt and/or command,并且它们一起可用于绕过或取消定义可能隐藏 shell 关键字、内置函数和外部实用程序的任何别名或 shell 函数。
    • 作为替代方案未定义功能,command可以用来bypass它们,包括那些可能已定义的outside您的代码,通过环境;
      出口函数,仅作为bash支持,只是one这些机制;不同的 shell 有不同的 shell,并且可能支持多个 - 见下文。
  • Only dash, ksh, and bash 当处于 POSIX 兼容模式时保证unset没有重新定义:

    • dash and ksh是安全的,因为他们不允许定义 a function named unset,正如您所发现的,任何别名形式都可以通过调用 as 来绕过\unset.

    • bash, 当处于 POSIX 兼容模式时,允许您define一个名为unset, but ignores当你调用它时unset,并且始终执行内置函数,正如您后来发现的那样。

      • 鉴于POSIX 兼容模式限制 Bash 的功能集并修改其行为,通常不希望在其中运行 Bash 代码。在这篇文章的底部是一个实现解决方法你建议,哪个暂时地激活 POSIX 兼容模式以确保不会unset function被定义为。
  • 可悲的是,据我所知,在zsh- 并且也在bash的默认模式 - 有没有办法保证unset本身还没有被重新定义,并且可能还有其他类似 POSIX 的 shell 具有类似的行为。

    • 称其为\unset(引用名称的任何部分)将绕过alias重新定义,但不是function重新定义 - 要撤消它,您需要原始的unset本身:第22条。
  • Thus, 由于无法控制执行环境,因此无法编写完全不受篡改的 shell 脚本, unless你知道你的代码将被执行dash, ksh, or bash(解决方法到位).

    • 如果你愿意假设unset没有被篡改过,最稳健的方法 is to:

      • Use \unset -f为了保证unalias and command未修改(未被 shell 函数遮蔽:\unset -f unalias command)

        • 与别名不同,函数必须是未定义的明确地,按名称,但不幸的是,并非所有 shell 都提供枚举所有已定义函数的机制(typeset -f工作于bash, ksh, and zsh, but dash似乎根本没有机制),以便取消定义all功能并不总是可行。
      • Use \unalias -a删除所有别名。

      • 然后调用一切 with command [-p],除了函数you已定义。调用时外部实用程序, use 显式路径在可能的情况下,和/或在以下情况下标准实用程序, use command -p,它使用最少的$PATH定义仅限于标准位置(运行command -p getconf PATH查看该定义)。


附加信息:

  • 根据 POSIX,引用命令名称的任何部分(例如,\unset)绕过任何alias形式或keyword form (保留字在 POSIX 和zsh说法)用这个名字 - 但是not shell 功能.

  • 根据 POSIX,unalias -a取消定义所有aliases。没有等效的、符合 POSIX 标准的命令来取消所有定义功能.

    • Caveat: older zsh版本做not支持-a;至少截至v5.0.8然而,他们确实这么做了。
  • Builtin command可用于绕过关键字、别名、函数bash, dash, and ksh- 换句话说:command只执行builtins and 外部实用程序。相比之下,zsh默认情况下also绕过builtins;使zsh也执行内置函数,使用options[POSIX_BUILTINS]=on.

  • 可以使用以下命令来执行external实用程序命名<name>仅在所有 shell 中:
    "$(command which <name>)" ...
    请注意,虽然which不是 POSIX 实用程序,它在现代类 Unix 平台上广泛使用。

  • 命令形式的优先级:

    • bash, zsh:别名> shell关键字> shell函数>内置>外部实用程序
    • ksh, dash:shell关键字>别名>shell函数>内置>外部实用程序
    • 即:在bash and zsh别名可以覆盖 shell 关键字,而在ksh and dash这不可以。
  • bash, ksh, and zsh- 但不是dash- 全部允许非标准函数签名,function <name> { ...,作为 POSIX 兼容的替代方案<name>() { ... form.

    • The function syntax is the prerequisite for:
      • 确保<name>本身不受别名扩展的影响before函数已定义。
      • 能够选择一个<name>那也是一个壳keyword;
        请注意,这样的函数可以only被调用于quoted形式;例如。,\while.
      • (如果是ksh, using function语法还意味着typeset语句创建local变量。)
    • dash, ksh, and bash 当处于 POSIX 模式时另外还可以防止命名函数special内置函数(例如,unset, break, set, shift);可以找到 POSIX 定义的特殊内置函数的列表here; both dash and ksh添加一些无法重新定义的内容(例如,local in dash; typeset and unalias in ksh),但是两个外壳都有额外的,非特殊的内置函数can被重新定义(例如,type).
      请注意,在以下情况下ksh上述规则无论是否适用均适用function使用或不使用语法。
  • 潜在来源环境外壳函数在您的代码范围内:

    • 注意:防止这些的最简单方法是使用(未修改的)command内置(在zsh with options[POSIX_BUILTINS]=on,以防止绕过内置函数)每当您想要调用内置或外部实用程序时。

    • POSIX 要求脚本由环境变量中的绝对路径指定ENV be sourced for 交互的shell(有一些限制 - 请参阅the spec); ksh and dash始终尊重这一点,而bash仅当调用时才会这样做sh或者,在 v4.2+ 中,--posix;相比之下,zsh从不尊重这个变量。

      • 注意:您的代码作为script通常会运行在非交互式shell,但这并不能保证;例如,您的代码可能是sourced从交互式脚本,或者有人可以调用您的脚本,例如sh -i强制交互式实例。
    • bash has 2机制:

      • 出口个人功能 with export -f or declare -fx(其他shell仅支持导出变量)
      • 每当出现时指定脚本的完整路径非交互式shell 在可选环境变量中启动BASH_ENV.
    • ksh支持自动加载通过可选的功能FPATH环境变量:包含位于指定的任何目录中的函数定义的文件FPATH are 隐式且自动地 loaded.

      • (zsh支持FPATH也是如此,但自动加载功能需要explicit autoload <name>声明,因此除非您明确要求自动加载给定名称的函数,否则不会将任何函数添加到您的 shell 中。)
    • zsh支持采购脚本any zsh实例(无论是否交互式)通过其/etc/zshenv and ~/.zhsenv初始化文件。

    • (dash貌似不支持any通过环境定义函数的机制。)


解决方法bash: 确保这件事unset它的本意是:

仅当您知道这一点时,此解决方法才是安全的bash将执行您的脚本,不幸的是,这本身无法得到保证。

此外,由于它修改了 shell 环境(删除别名和函数),因此它不适合以下脚本:设计用于采购.

如前所述,通常不希望在 Bash 的 POSIX 兼容模式下运行代码,但您可以暂时地激活它以确保unset没有被函数遮盖:

#!/bin/bash

# *Temporarily* force Bash into POSIX compatibility mode, where `unset` cannot 
# be shadowed, which allows us to undefine any `unset` *function* as well
# as other functions that may shadow crucial commands.
# Note: Fortunately, POSIXLY_CORRECT= works even without `export`, because
#       use of `export` is not safe at this point.
#       By contrast, a simple assignment cannot be tampered with.
POSIXLY_CORRECT=

# If defined, unset unset() and other functions that may shadow crucial commands.
# Note the \ prefix to ensure that aliases are bypassed.
\unset -f unset unalias read declare

# Remove all aliases.
# (Note that while alias expansion is off by default in scripts, it may
#  have been turned on explicitly in a tampered-with environment.)
\unalias -a  # Note: After this, \ to bypass aliases is no longer needed.

# Now it is safe to turn POSIX mode back off, so as to reenable all Bash
# features.
unset POSIXLY_CORRECT

# Now UNDEFINE ALL REMAINING FUNCTIONS:
# Note that we do this AFTER switching back from POSIX mode, because
# Bash in its default mode allows defining functions with nonstandard names
# such as `[` or `z?`, and such functions can also only be *unset* while
# in default mode.
# Also note that we needn't worry about keywords `while`, `do` and `done`
# being shadowed by functions, because the only way to invoke such functions
# (which you can only define with the nonstandard `function` keyword) would
# be with `\` (e.g., `\while`).
while read _ _ n; do unset -f "$n"; done < <(declare -F)

# IN THE REST OF THE SCRIPT:
#  - It is now safe to call *builtins* as-is.
#  - *External utilities* should be invoked:
#      - by full path, if feasible
#      - and/or, in the case of *standard utilities*, with
#        command -p, which uses a minimal $PATH definition that only
#        comprises the locations of standard utilities.
#      - alternatively, as @jarno suggests, you can redefine your $PATH
#        to contain standard locations only, after which you can invoke
#        standard utilities by name only, as usual:
#          PATH=$(command -p getconf PATH)

# Example command:
# Verify that `unset` now refers to the *builtin*:
type unset

测试命令:

假设上面的代码被保存到文件中script在当前目录中。

以下命令模拟一个被篡改的环境,其中unset被别名和函数所遮蔽,并且文件script is sourced,使其看到该函数,并且当以交互方式获取时,也扩展别名:

$ (unset() { echo hi; }; alias unset='echo here'; . ./script)
unset is a shell builtin

type unset输出unset is a shell builtin证明函数和别名都遮盖了内置函数unset被停用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用纯 unset shell 内置函数?你能编写不受篡改的 shell 脚本吗? 的相关文章

  • -bash: gulp: 在 Mac 中找不到命令

    我尝试在 mac 中安装 gulp 如下所示 Is iMac itop npm root Users itop node modules Is iMac itop npm config set prefix usr local Is iMa
  • Bash 完成脚本在某些参数选项后完成文件路径

    我正在为命令行工具编写 bash 完成脚本 plink local cur prev opts COMPREPLY cur COMP WORDS COMP CWORD prev COMP WORDS COMP CWORD 1 opts 1
  • Bash - 如何将参数传递给通过标准输入读取的脚本

    我正在尝试从标准输入执行脚本并将参数传递给它 有办法做到吗 假设我有以下内容 cat script sh bash 我如何将参数传递给脚本 我不想这样做 bash script sh arguments 也不是这个 script sh ar
  • 从重定向到日志文件的程序输出中删除进度条

    我正在运行一个程序 它会输出进度条 我是这样做的 python train py tee train log The train log看起来像下面这样 这是1号线 Training 这是2号线 000 valid 100 2630 263
  • 将 stdout 作为命令行 util 的文件名传递?

    我正在使用一个命令行实用程序 该实用程序需要传递文件名以将输出写入 例如 foo o output txt 它唯一写入的东西stdout是一条消息 表明它运行成功 我希望能够通过管道传输写入的所有内容output txt到另一个命令行实用程
  • openssl_crypt 中初始化向量的使用

    我看了一下this https stackoverflow com questions 1391132 two way encryption in php问题 并想为自己做 当我运行这段代码时 直接取自这个答案 https stackove
  • 让 Emacs ansiterm 和 Zsh 更好地发挥作用

    我一直在尝试在 emacs 会话中使用 Zsh 而无需 emacs 重新映射所有 Zsh 键 我发现 ansi term 对此非常有效 但是我仍然遇到一些问题 我输出了很多垃圾字符 我可以用以下方法修复它 Setup proper term
  • 用户如何登录定义了读者角色的 couchapp?

    我通过 Couchapp 部署了我的应用程序 这意味着整个应用程序是从数据库中提供服务的 我不希望 Couchdb 数据库中的数据公开可用 因此我指定了用户在向他提供数据之前必须具有的读者角色 然而 当我去申请时 我所能得到的是 error
  • 从 bash 脚本运行节点

    很简单 我正在尝试使用 cron 自动运行 nodejs 脚本 但是脚本本身似乎无法运行该文件 我的脚本很简单 usr bin env node node var node assets js update js 但是 在运行此命令时 它返
  • 如何在 C# 中创建 PKCS12 .p12 文件?

    这可能是一个n00b问题 但我在这方面确实没有任何经验 我需要创建一个包含 X509 证书和私钥的 p12 捆绑包 我当前有两个对象 X509Certificate2 和包含关键信息的 RSAParameters 对象 如何将它们合并到 p
  • 使用Sed查找并替换json字段

    我有一组 json 文件 其中在最后一个键值对之后有需要替换的逗号 RepetitionTime 0 72 TaskName WM Manufacturer Siemens ManufacturerModelName Skyra Magne
  • 解码 OAEP 填充时出错

    我的问题已经解决了一半 请帮助 我已使用数字签名的公钥成功加密了文本 但在解密时出现错误 解码 OAEP 填充时出错 我的代码如下 region Test Encryption public void a using var rsa new
  • 如何复制每个扩展名为 X 的文件,同时保留原始文件夹结构? (类Unix系统)

    我正在尝试将每个 HTML 文件从 src 文件夹复制到 dist 文件夹 但是 我想保留原始文件夹结构 如果 dist 文件夹不存在 我想创建一个新文件夹 如果文件夹不存在则创建 d dist mkdir dist 复制每个文件 cp R
  • 使用 mkfifo 和传输流,这可能吗?

    我想执行一个 bash 脚本来执行以下操作 应用程序 ffmpeg 生成实时传输流 ts 文件 我需要处理这个实时流 执行解复用等 现在我知道这必须通过 FIFO 来完成 但这是我的任务 我需要重定向 ffmpeg 的输出以写入 fifo
  • 如何列出静态链接的 python 版本中可用的所有 openssl 密码?

    在python 2 7 8到2 7 9升级中 ssl模块从使用更改为 DEFAULT CIPHERS DEFAULT aNULL eNULL LOW EXPORT SSLv2 to DEFAULT CIPHERS ECDH AESGCM D
  • Bash - 在 perl 正则表达式中使用变量以及匹配组

    这是我在 stackoverflow 上的第一篇文章 如果我错过了一些重要的内容 请原谅我 我目前遇到以下问题 目标是根据我准备的文件列表动态替换端口号find 这些文件中的所有端口均以数字 4 开头 有 5 位数字 现在是棘手的部分 我只
  • BASH 脚本编译多个 C++ 文件 - OpenCV

    请参见在C 和OpenCV中调用其他文件中的函数 https stackoverflow com questions 24442836 call functions in other files in c and opencv 对于最初的问
  • Bash 脚本:#!/bin/bash 是什么意思? [复制]

    这个问题在这里已经有答案了 在 bash 脚本中 什么是 bin bash第一行是什么意思 UPDATE 有区别吗 bin bash and bin sh 这就是所谓的shebang http en wikipedia org wiki S
  • 用于防止滥用的 Servlet 过滤器? (DoS、垃圾邮件等)

    我正在寻找一个 Servlet 过滤器库 它可以帮助我保护我们的 Web 服务免受未经授权的使用和 DDoS 攻击 我们的网络服务有 授权客户 因此理想情况下 过滤器将帮助检测未经授权或行为不当的客户 或检测使用同一帐户的多个人 此外 我们
  • 将数组传递给函数名称冲突

    Specs GNU bash 版本 3 1 17 无法升级 Premise 我一直在摆弄数组 我想知道是否有任何方法可以让函数的本地变量与所述函数外部的数组同名 Example 在下面的示例中 我将尝试显示该问题 Working bin b

随机推荐