【问题标题】:Is it possible to execute a bash script with root permission from NGINX and get the output?是否可以使用 NGINX 的 root 权限执行 bash 脚本并获取输出?
【发布时间】:2018-03-09 13:05:03
【问题描述】:

我在 Openresty 构建下运行 Nginx,因此启用了 Lua 脚本。我想创建一个 URI 位置(除了 IP 白名单外,还将使用 SSL +身份验证进行保护),它允许来自授权来源的 webhook 调用使用 root 权限在服务器上执行 bash 脚本。例如

https://someserver.com/secured/exec?script=script.sh&param1=uno&param2=dos

NGINX 将使用 'script' 和 'param#' GET 请求参数在 shell 中执行“script.sh uno dos”。它捕获脚本输出和 bash 返回代码(如果可能的话)。

我了解以 root 身份运行 NGINX 并运行任意命令的安全隐患,但如前所述,对 URI 的访问是安全的。

这是否可以通过本机 NGINX 模块或 Lua 脚本实现?有什么示例代码可以让我开始吗?

谢谢。

【问题讨论】:

  • 使用github.com/jprjr/lua-resty-execgithub.com/juce/lua-resty-shell。以 root 身份启动 Sockproc。
  • 谢谢。我想知道是否有一种不需要运行守护进程的方法。似乎 lua os.execute 可以运行 shell 命令,但不能返回其输出或状态码。我想创建一个 bash 包装脚本,它采用脚本名称和它的 args(因为它是自己的 args)并运行它。然后将输出和退出代码转储到文本文件中,以便 Lua 可以读取它们。 Prob 应该将唯一的 ID 传递给包装脚本以用作文件名,以确保没有两个调用覆盖同一个文件。我想知道是否有人能想到更清洁的解决方案。

标签: nginx lua luajit openresty


【解决方案1】:

还有另一种可能的解决方案,不需要额外的 nginx lua 插件。这是使用socat。你在端口 8080 上启动一个 socat,它在每个连接上执行一个 bash 脚本

socat TCP4-LISTEN:8080,reuseaddr,fork EXEC:./test.sh

test.sh

#!/bin/bash

recv() {
    echo "< $@" >&2;
}

read line
line=${line%%$'\r'}
recv "$line"

read -r REQUEST_METHOD REQUEST_URI REQUEST_HTTP_VERSION <<<"$line"

declare -a REQUEST_HEADERS

while read -r line; do
    line=${line%%$'\r'}
    recv "$line"

    # If we've reached the end of the headers, break.
    [ -z "$line" ] && break

    REQUEST_HEADERS+=("$line")
done
eval $(echo $REQUEST_URI | awk -F? '{print $2}' | awk -F'&' '{for (i=1;i<=NF;i++) print $i}')


cat <<END1
HTTP/1.1 200 OK
Content-Type: plain/text

REQUEST_METHOD=$REQUEST_METHOD
REQUEST_URI=$REQUEST_URI
REQUEST_HTTP_VERSION=$REQUEST_HTTP_VERSION
REQUEST_HEADERS=$REQUEST_HEADERS
script=$script
param1=$param1
param2=$param2
END1

卷曲测试如下

$ curl "localhost:8080/exec?script=test2.sh&param1=abc&param2=def"
REQUEST_METHOD=GET
REQUEST_URI=/exec?script=test2.sh&param1=abc&param2=def
REQUEST_HTTP_VERSION=HTTP/1.1
REQUEST_HEADERS=Host: localhost:8080
script=test2.sh
param1=abc
param2=def

因此,您可以轻松地将其用于 nginx 中的proxy_pass

如果您需要使用 socat 在 bash 中查看完整的服务器,请查看 https://github.com/avleen/bashttpd/blob/master/bashttpd

【讨论】:

  • 很有创意...我喜欢你的风格
  • 缺少连字符,我认为应该是这样的:recv() { echo "&lt; $@" &gt;&amp;2; } read -r line
猜你喜欢
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
  • 2014-01-08
  • 2011-09-15
  • 2012-12-18
  • 2021-07-13
相关资源
最近更新 更多