在Alpine Docker镜像中使用SUID

8
我想在 Alpine Docker 镜像中以不同用户身份运行一些脚本。在以 devuser 登录的情况下,我想将 setup.sh 作为 root 运行,并将 app.sh 作为 appuser 运行。由于我已阅读到无法对脚本文件使用 SUID,因此我有几个 C 程序,setupapp,它们会调用这些脚本。我可以将 setup 作为 root 运行,但不能将 app 作为 appuser 运行。

以下是目录内容。请注意,app 和 setup 对程序设置了 SUID 位。我尝试将 SUID 设置在脚本上,但没有成功。

/opt/app $ ls -l
total 24552
-r-sr-xr-x    1 appuser  appgroup     10632 Jun 27 12:59 app
-r--------    1 appuser  appgroup  25101769 Jun 27 12:59 app.jar
-r-xr-xr--    1 appuser  appgroup       327 Jun 27 12:59 app.sh
-r--------    1 appuser  appgroup       316 Jun 27 12:59 application.yml
-r-sr-xr-x    1 root     root         10632 Jun 27 12:59 setup
-r-xr-xr--    1 root     root           152 Jun 27 12:59 setup.sh

我正在以 devuser 的身份运行。

/opt/app $ whoami
devuser

我成功运行了setup。它属于root并作为root运行。

/opt/app $ ./setup
Running As: root:appgroup

我尝试运行app,但它没有更改所有者。

/opt/app $ ./app
Running As: devuser:appgroup
Error: Unable to access jarfile app.jar

这里是setup.sh的源代码。
/opt/app $ cat setup.sh
#!/bin/ash

echo "Running As: $(whoami):$(id -gn)"

这里是app.sh的源代码。
/opt/app $ cat app.sh
#!/bin/ash

echo "Running As: $(whoami):$(id -gn)"

java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar $SPRING_OPTS

以下是两个用户。

/opt/app $ id devuser
uid=701(devuser) gid=700(appgroup) groups=700(appgroup),700(appgroup)

/opt/app $ id appuser
uid=700(appuser) gid=700(appgroup) groups=700(appgroup),700(appgroup)

这是 setup.c 的源代码。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    setuid(0);
    system("./setup.sh");
    return 0;
}

这里是app.c的源代码。我也尝试过使用setuid(0),但没有成功。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    setuid(700);
    system("./app.sh");
    return 0;
}

最后是我的问题;Docker构建. 我尝试将 adduser 设置为系统用户和非系统用户.

RUN    addgroup -g 700 appgroup \
    && adduser -G appgroup -D -u 700 -S -H -s /bin/sh appuser \
    && adduser -G appgroup -D -u 701 -s /bin/sh devuser

RUN    sh -c 'touch app.jar' \
    && chown appuser:appgroup *.jar  \
    && chown appuser:appgroup *.yml  \
    && chown appuser:appgroup app.sh  \
    && chown appuser:appgroup app \
#    && chmod -R 750 . \
    && chmod u+x,g+x,o-x *.sh \
    && chmod 4555 setup \
    && chmod 4555 app \
    && chmod 400 *.yml \
    && chmod 400 *.jar \
    && chmod -R -w .

USER devuser
# USER appuser

感谢您的帮助,Wes。
1个回答

2
如果您在app.c中将setuid()更改为setreuid(),它将起作用。
请参见此答案和评论以了解原因:https://dev59.com/hHrZa4cB1Zd3GeqP2nMN#20687988
然而,您描述的方法是非标准的。在SUID二进制文件中调用shell脚本听起来像是hacky。
以下是使用Alpine标准的su-exec的方法:
app.sh
#!/bin/sh

echo "Running As: $(whoami):$(id -gn)"

java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar app.jar $SPRING_OPTS

setup.sh

#!/bin/sh

echo "Running As: $(whoami):$(id -gn)"

exec su-exec appuser:appgroup ./app.sh

Dockerfile

FROM alpine

WORKDIR /app

RUN apk add --no-cache su-exec

RUN    addgroup -g 700 appgroup \
    && adduser -G appgroup -D -u 700 -S -H -s /bin/sh appuser

COPY * ./

RUN chmod 0755 *.sh

ENTRYPOINT ["./setup.sh"]

更简单,也可能更安全。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接