强制cURL从环境中获取密码

Ada*_*atz 15 security bash curl environment-variables sh

有关使用卷曲用户名和密码的问题,对我来说最理想的答案:

  1. curl -u "user:pw" https://example.com 将pw放入进程列表中
  2. curl "https://user:pw@example.com" 将pw放入进程列表中
  3. curl -u "user:$(cat ~/.passwd)" https://example.com 将pw放入进程列表中
  4. curl -u user https://example.com 提示pw
  5. curl --netrc-file ~/.netrc https://example.com 需要一个文件

#4是安全的,但我可能每天运行这个命令数百次,所以这很乏味.#5接近安全,但是具有root访问权限的人可以读取该文件.

卷曲手册页说(注意粗体文本):

-u/--user <user:password>

指定用于服务器身份验证的用户名和密码.覆盖-n/--netrc--netrc-optional.

如果您只是提供用户名(不输入冒号),curl将提示输入密码.

如果您使用启用SSPI的curl二进制文件并执行NTLM身份验证,则可以 通过使用以下选项指定单个冒号来强制curl从您的环境中获取用户名和密码:-u :.

我已经尝试在环境中设置$USER$PASSWORD(以及$CURLOPT_PASSWORD其他),但是cURL在调用时不会选择其中任何一个curl -u : https://example.com(如果没有它也没有-u :).

我不是在做NTLM,所以这不起作用.除非我错过了什么.

 

有没有办法将凭证传递给curl环境?

 

(解决方法转到答案)

Ada*_*atz 19

bash解决方案似乎最符合我的需求.它非常安全,便携且快速.

#!/bin/bash
SRV="example.com"
URL="https://$SRV/path"
curl --netrc-file <(cat <<<"machine $SRV login $USER password $PASSWORD") "$URL"
Run Code Online (Sandbox Code Playgroud)

这使用进程替换(在子shell中<( command )运行command以填充文件描述符作为"文件"传递给父命令,在这种情况下是curl).进程替换包含here-string(cat <<< text其变体echo text不会将任何内容放入进程列表中),为netrc文件创建文件描述符以便将凭据传递给远程Web服务器.

进程替换提供的安全性实际上非常合理:它的文件描述符不是临时文件,即使在同一个shell实例中的其他调用也不可用,因此在此上下文中看起来是安全的.对手必须通过内存挖掘或发动复杂的攻击才能找到其内容.由于$PASSWORD环境变量也在内存中,因此不应增加攻击面.

只要您没有使用过export PASSWORD,就不ps ewwp $$应该泄露密码(如本评论中所述).使用一些不太明显的变量名称也是明智之举.

以下是上述代码的简化不安全版本,可能有助于解释它的工作原理:

#!/bin/sh
# INSECURE VERSION, DO NOT USE
SRV=example.com
URL="https://$SRV/path"
TMP=$(mktemp)
printf "machine %s login %s password %s\n" "$SRV" "$USER" "$PASSWORD" > "$TMP"
curl --netrc-file "$TMP" "$URL"
rm -f "$TMP"
Run Code Online (Sandbox Code Playgroud)

这个不安全的版本有很多缺陷,所有这些都在以前的版本中得到了解决:

  • 它将密码存储在一个文件中(尽管该文件只对您有用)
  • 它在命令行中非常简短地有密码
  • 临时文件一直保留到退出 curl
  • Ctrl+ c将退出而不删除临时文件

其中一些可以通过以下方式解决:

#!/bin/sh
SRV=example.com
URL="https://$SRV/path"
TMP=$(mktemp /dev/shm/.XXXXX)  # assumes /dev/shm is a ramdisk
trap "rm -f $TMP" 0 18
cat << EOF > "$TMP"
machine $SRV login $USER password $PASSWORD
EOF
(sleep 0.1; rm -f "$TMP") &  # queue removing temp file in 0.1 seconds
curl --netrc-file "$TMP" "$URL"
Run Code Online (Sandbox Code Playgroud)

我认为这个版本是凌乱的,次优的,可能不太安全(虽然它更便携).它还需要一个sleep可以理解小数的版本(如果系统负载很重,则0.1秒可能太快).

 


我最初perl在我的问题中发布了一个包含单行的解决方法,然后(在Etan Reisner的帮助下)我在解决这个字符串方法之前已经完成了一些更好的方法,这个方法既轻量级(更快)又更便携.

在这一点上,它足够优雅,我认为它是"答案",而不是"丑陋的解决方法",所以我把它迁移到这个官方答案.我已经给了@ghoti一个+1 的答案,它正确地指出cURL的命令行程序无法自己做我想要的,但我不是"接受"那个答案,因为它没有帮助解决问题.

  • 如果您的 shell 的 `echo` 命令是内置命令,则可以安全地将 `&lt;(cat &lt;&lt;&lt;"$PASSWORD")` 替换为 `&lt;(echo "$PASSWORD")`。$PASSWORD 将不会出现在进程表中。在 bash 中,可以使用 type -t echo 来测试 echo 是否是内置函数。 (2认同)
  • 如果您对“-K/--config”使用相同的方法,它确实有效!([参见](/sf/answers/3726956411/)) `curl --config &lt;(echo user=用户名:密码) --location https://example.com/redirect?id=42` (2认同)

gho*_*oti 8

有没有办法将凭证传递给curl环境?

不,我认为没有.

CURLOPT_USERPWD文档我想介绍你所需要的,但是这是将使用curl库在其他语言可用的选项.PHP,Perl,C等

从shell运行的curl二进制文件只是该库的另一个前端,但是通过curl二进制文件将CURLOPT_USERPWD传递给库的方式是使用二进制文件上的命令行选项.

理论上,您可以将自己的二进制文件编写为curl库的前端,并编写支持环境变量.

您可以交替破解环境支持,因为您希望将其视为现有的curl二进制文件,并使用本地函数编译自己的.

但请注意,即使环境变量可能会被shell泄漏到进程表中.(你跑步时看到了什么ps ewwp $$?)

也许具有受限权限的.netrc文件将是最安全的方式.也许你需要生成一个临时的.netrc文件供--netrc-filecurl选项使用.

我认为你要么必须为你的环境选择风险最小的解决方案,要么用真正安全的语言写一些东西.


sfg*_*rge 6

用户“Tom, Bom”在这里提供了一个不错的解决方案:https : //coderwall.com/p/dsfmwa/securely-use-basic-auth-with-curl

curl --config - https://example.com <<< 'user = "username:password"'
Run Code Online (Sandbox Code Playgroud)

这可以防止密码出现在进程列表中,尽管这并没有专门解决 OP 的原始问题:

有没有办法传递凭据以仅在环境中卷曲?

我仍然给@goti 加分,因为他们给出了更全面、更翔实的答案。


gre*_*pit 5

以前的答案是正确的,最好的选择是使用 -n 进行curl(假设你在linux上):

  1. 创建一个文件(使用您自己喜欢的编辑器)

vi ~YOUR_USER_NAME/.netrc

  1. 添加以下内容

machine example.com login YOUR_USER_NAME password THE_ACTUAL_PASSWORD

  1. 跑步

curl -n https://example.com/some_end_point

  • 我对此进行了测试(尽管您可以随意亲自测试并分享任何矛盾的发现)。正如我的回答中明确指出的那样,**此处字符串内容不会显示在进程列表中**(`ps -ef|grep curl`将向您显示类似`curl --netrc-file /proc/self/fd/ 18 http://…`)。这就是它起作用的全部原因。请完整阅读我的回答,因为所有这些都在那里进行了详细讨论。如果你阅读我的问题、我的答案和 ghoti 的答案中的评论,还有更多内容。 (4认同)
  • 这是建议将密码存储在文件中的唯一答案。我的问题是关于如何_在环境中_使用密码,**特别是这样它永远不会访问文件系统**。这里的其他答案都不涉及实际文件;它们仅使用像文件一样对待的 shell 构造。 (2认同)

Rob*_*ade 4

Curl 在解析 netrc 文件中的标记时使用 SPACE 和 TAB 作为分隔符:

\n

https://github.com/curl/curl/blob/bc5a0b3e9f16a431523ae54822adc38c3a396a26/lib/netrc.c#L122

\n

因此,该--netrc-file方法无法处理密码中的空格或制表符。

\n

测试密码中的空格

\n
SRV="httpbin.org"\nURL="https://$SRV/basic-auth/username/pass%20word"\nUSERNAME=username\nPASSWORD=\'pass word\'\ncurl -v --netrc-file <(echo "machine $SRV login $USERNAME password $PASSWORD") "$URL"\n
Run Code Online (Sandbox Code Playgroud)\n

结果:\xe2\x9d\x8c 失败

\n
\n

警告:如果您的 shell 命令echo不是内置命令,则上述curl 调用将暂时将 $PASSWORD 泄漏到进程表中。中bash,是否echo是内置的可以用 来测试type -t echo。解决方法:使用cat和 这里的字符串:替换<(echo "string")<(cat <<< "string"). 此警告适用于本答案中的所有示例。

\n
\n

密码TAB测试

\n
SRV="httpbin.org"\nURL="https://$SRV/basic-auth/username/pass%09word"\nUSERNAME=username\nPASSWORD=$\'pass\\tword\'\ncurl -v --netrc-file <(echo "machine $SRV login $USERNAME password $PASSWORD") "$URL"\n
Run Code Online (Sandbox Code Playgroud)\n

结果:\xe2\x9d\x8c 失败

\n

更稳健的方式

\n

@sfgeorge 正确地指出,设置为 的-K, \xe2\x80\x89--config <file>选项可用于在 STDIN 上提供密码。但是,将 STDIN 用于此目的会妨碍将 STDIN 用于其他目的,例如使用.<file>---data @-

\n

幸运的是,我们可以使用进程替换来代替 STDIN。进程替换扩展为文件名,因此可以在需要文件名的任何地方使用。

\n

测试密码中的空格

\n
USERNAME=username\nPASSWORD=\'pass word\'\ncurl -v \\\n  -K <(echo "user: \\"$USERNAME:$PASSWORD\\"") \\\n  "https://httpbin.org/basic-auth/username/pass%20word"\n
Run Code Online (Sandbox Code Playgroud)\n

结果:\xe2\x9c\x85 成功

\n

密码TAB测试

\n
USERNAME=username\nPASSWORD=$\'pass\\tword\'\ncurl -v \\\n  -K <(echo "user: \\"$USERNAME:$PASSWORD\\"") \\\n  "https://httpbin.org/basic-auth/username/pass%09word"\n
Run Code Online (Sandbox Code Playgroud)\n

结果:\xe2\x9c\x85 成功

\n

而且,为了额外的稳健性,我们让它也处理密码中的双引号。

\n

"密码中双引号的测试

\n
USERNAME=username\nPASSWORD=$\'pa s\\ts"wo$rd\'\n\n# Build \'user\' option\nUSER_OPT="$USERNAME:$PASSWORD"\nUSER_OPT=${USER_OPT//\\\\/\\\\\\\\} # Escape `\\`\nUSER_OPT=${USER_OPT//\\"/\\\\\\"} # Escape `"`\nUSER_OPT="user: \\"${USER_OPT}\\""\n\ncurl -v \\\n  -K <(echo "$USER_OPT") \\\n  "https://httpbin.org/basic-auth/username/pa%20s%09s%22wo%24rd"\n
Run Code Online (Sandbox Code Playgroud)\n

结果:\xe2\x9c\x85 成功

\n

为了更好地衡量,我还添加了一个表情符号。

\n