

[CentOS]
编译过程如下,安装包开发工具:
yum install -y rpm-build
Install packages necessary for building openssh
yum install -y gcc openssl-devel pam-devel
Download openssh sources
wget http://mirror.aarnet.edu.au/pub/OpenBSD/OpenSSH/portable/openssh-6.2p2.tar.gz
wget http://mirror.aarnet.edu.au/pub/OpenBSD/OpenSSH/portable/openssh-6.2p2.tar.gz.asc
wget http://mirror.aarnet.edu.au/pub/OpenBSD/OpenSSH/portable/DJM-GPG-KEY.asc
gpg --import DJM-GPG-KEY.asc
gpg openssh-6.2p2.tar.gz.asc
Copy info to redhat build tree
cp openssh-6.2p2.tar.gz /usr/src/redhat/SOURCES/
tar -xzvf openssh-6.2p2.tar.gz
cp openssh-6.2p2/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/
Remove the X11 and Gnome stuff (since we are building for a server) from the spec file
vi /usr/src/redhat/SPECS/openssh.spec
%define no_x11_askpass 0
%define no_gnome_askpass 0
或者用perl来修改spec文件
perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec
开始建包
rpmbuild -bb /usr/src/redhat/SPECS/openssh.spec
cd /usr/src/redhat/RPMS/`uname -i`
ls -l
-rw-r--r-- 1 root root 275808 Feb 27 08:08 openssh-6.2p2-1.x86_64.rpm
-rw-r--r-- 1 root root 439875 Feb 27 08:08 openssh-clients-6.2p2-1.x86_64.rpm
-rw-r--r-- 1 root root 277714 Feb 27 08:08 openssh-server-6.2p2-1.x86_64.rpm
rpm -Uvh openssh*rpm
service sshd reload|restart
查看ssh客户端的版本
ssh --version
关于升级后用户不能登录的问题,可以参考文章后面解决办法。
[Debian]
从临近的源站上下载对应包
wget http://mirrors.163.com/debian/pool/main/o/openssh/openssh_6.2p2-6.dsc
wget http://mirrors.163.com/debian/pool/main/o/openssh/openssh_6.2p2-6.debian.tar.gz
wget http://mirrors.163.com/debian/pool/main/o/openssh/openssh_6.2p2.orig.tar.gz
将openssh_6.2p2.orig.tar.gz包将压,后将openssh_6.2p2-6.debian.tar.gz解压出来的'debian'目录移动到'openssh-6.2p2'目录下。'.dsc'文件是不需要的,打包需要使用'dpkg-buildpackage'指令来实现。
dpkg-checkbuilddeps: Unmet build dependencies: libwrap0-dev | libwrap-dev libssl-dev (>= 0.9.8g) libpam0g-dev | libpam-dev libgtk2.0-dev libedit-dev libselinux1-dev libkrb5-dev | heimdal-dev libck-connector-dev dh-autoreconf autotools-dev
安装相关依赖软件包
apt-get install libwrap0-dev libwrap0-dev libssl-dev libpam0g-dev libgtk2.0-dev libedit-dev libselinux1-dev heimdal-dev libck-connector-dev dh-autoreconf autotools-dev libwrap-dev libpam-dev
进入'openssh-6.2p2'目录,执行指令:dpkg-buildpackage,编译完成后会在上级目录生成对应的软件包。
openssh-client_6.2p2-6_amd64.deb
openssh-server_6.2p2-6_amd64.deb
ssh_6.2p2-6_all.deb
ssh-krb5_6.2p2-6_all.deb
ssh-askpass-gnome_6.2p2-6_amd64.deb
openssh-client-udeb_6.2p2-6_amd64.udeb
openssh-server-udeb_6.2p2-6_amd64.udeb
# dpkg -i *.deb
(正在读取数据库 ... 系统当前共安装有 54620 个文件和目录。)
正预备替换 openssh-client 1:6.2p2-6 (使用 openssh-client_6.2p2-6_amd64.deb) ...
正在解压缩将用于更替的包文件 openssh-client ...
正预备替换 openssh-server 1:6.2p2-6 (使用 openssh-server_6.2p2-6_amd64.deb) ...
正在解压缩将用于更替的包文件 openssh-server ...
Selecting previously unselected package ssh.
正在解压缩 ssh (从 ssh_6.2p2-6_all.deb) ...
Selecting previously unselected package ssh-askpass-gnome.
正在解压缩 ssh-askpass-gnome (从 ssh-askpass-gnome_6.2p2-6_amd64.deb) ...
Selecting previously unselected package ssh-krb5.
正在解压缩 ssh-krb5 (从 ssh-krb5_6.2p2-6_all.deb) ...
正在设置 openssh-client (1:6.2p2-6) ...
正在处理用于 man-db 的触发器...
正在设置 ssh-askpass-gnome (1:6.2p2-6) ...
正在设置 openssh-server (1:6.2p2-6) ...
[ ok ] Restarting OpenBSD Secure Shell server: sshd.
正在设置 ssh (1:6.2p2-6) ...
正在设置 ssh-krb5 (1:6.2p2-6) ...
[ ok ] Restarting OpenBSD Secure Shell server: sshd.
视情况可能要安装'heimdal-dev'包,
dpkg: dependency problems prevent configuration of ssh-askpass-gnome:
ssh-askpass-gnome 依赖于 libglib2.0-0 (>= 2.12.0);然而:
未安装软件包 libglib2.0-0。
ssh-askpass-gnome 依赖于 libgtk2.0-0 (>= 2.8.0);然而:
未安装软件包 libgtk2.0-0。
dpkg: error processing ssh-askpass-gnome (--install):
依赖关系问题 - 仍未被配置
正在处理用于 man-db 的触发器...
正在设置 openssh-server (1:6.2p2-6) ...
Creating SSH2 RSA key; this may take some time ...
Creating SSH2 DSA key; this may take some time ...
Creating SSH2 ECDSA key; this may take some time ...
[ ok ] Starting OpenBSD Secure Shell server: sshd.
正在设置 ssh (1:6.2p2-6) ...
正在设置 ssh-krb5 (1:6.2p2-6) ...
[ ok ] Restarting OpenBSD Secure Shell server: sshd.
在处理时有错误发生:
ssh-askpass-gnome
可以在安装不安装ssh-askpass-gnome包,debian下需要在安装的编译控制文件进行设置,以排除生成此类包。从源码包不能打其它的补丁,否则会造成编译打包失败。
[总结]
升级的过程总结如下:
远程关闭了openssh服务后,ssh连接依然可用,可以放心升级。甚至可以在当前连接中将openssh卸载掉,也不会中断本次连接(只要不是连接断开),但不能新建连接了。在第三方源中也有openssh的新版本,但同时会影响其它软件的依赖关系。
[centos升级后不能登录的问题]
PAM unable to dlopen(/lib64/security/pam_stack.so): /lib64/security/pam_stack.so: cannot open shared object file: No such file or directory
不能再用原来的pam.d/sshd文件了,需要新的写法,其大致内容如下:
#%PAM-1.0
auth include system-auth
account required pam_nologin.so
account include system-auth
password include system-auth
session optional pam_keyinit.so force revoke
session include system-auth
session required pam_loginuid.so
在CentOS 7上从源码包安装升级openssh 8.0的过程记录
需要在同版本同架构的机器编译安装好它,后将所有的安装文件做一个包(sshv8.tar),它内置了一份配置文件,侦听的端口在6543上,下载该包到各台机器上解压使用。将要升级的机器的ip写到st.ssh文件中,每行一个,并做好了ssh autologin。
安装fuser
for h in $(cat st.ssh);do echo "$h:" && ssh -p 6543 $h 'yum install psmisc -y';done
下载并解压
cd /tmp && curl -O http://172.18.xx.57/sa/sf/sshv8.tar && tar -xf sshv8.tar -C /opt
for h in $(cat st.ssh);do echo "$h:" && ssh $h 'cd /tmp && curl -O http://ip:port/sa/sf/sshv8.tar && tar -xvf sshv8.tar -C /opt';done
同步老配置文件到新目录下,只同步已有的key并修改它的权限
/usr/bin/rsync -av /etc/ssh/ /opt/ssh/etc/ --exclude=*_config && chmod go-rwx /opt/ssh/etc/ssh_host_*
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/usr/bin/rsync -av /etc/ssh/ /opt/ssh/etc/ --exclude=*_config && chmod go-rwx /opt/ssh/etc/ssh_host_*';done
测试新的ssh服的配置文件
/opt/ssh/sbin/sshd -t -f /opt/ssh/etc/sshd_config
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/opt/ssh/sbin/sshd -t -f /opt/ssh/etc/sshd_config';done
拉起新的sshd服务
/opt/ssh/sbin/sshd -f /opt/ssh/etc/sshd_config
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/opt/ssh/sbin/sshd -f /opt/ssh/etc/sshd_config';done
加入到自启动中(至少在rc.local中)
chmod a+x /etc/rc.d/rc.local && echo "/opt/ssh/sbin/sshd -f /opt/ssh/etc/sshd_config" >> /etc/rc.d/rc.local
for h in $(cat st.ssh);do echo "$h:" && ssh $h 'chmod a+x /etc/rc.d/rc.local && echo "/opt/ssh/sbin/sshd -f /opt/ssh/etc/sshd_config" >> /etc/rc.d/rc.local';done
转移置换ssh端口:新版本的sshd侦听到22端口,老版本的换到5222端口做为备用通道。
先看一下sshd的状态(最好关闭防火墙)
for h in $(cat st.ssh);do echo "$h:" && ssh $h 'systemctl status sshd';done
for h in $(cat st.ssh);do echo "$h:" && ssh $h 'systemctl status firewalld';done
老版本转移:22->5222
sed -i "s/#Port 22/Port 5222/g" /etc/ssh/sshd_config && /usr/bin/systemctl restart sshd
for h in $(cat st.ssh);do echo "$h:" && ssh $h 'sed -i "s/#Port 22/Port 5222/g" /etc/ssh/sshd_config && /usr/bin/systemctl restart sshd';done
注意不能再用22端口连ssh了,有5222或6543可选,查看一下老版本的端口是否生效。
/usr/sbin/fuser 5222/tcp
for h in $(cat st.ssh);do echo "$h:" && ssh -p 6543 $h '/usr/sbin/fuser 5222/tcp';done
新版本转移:
6543->22
sed -i "s/Port 6543/Port 22/g" /opt/ssh/etc/sshd_config && /usr/sbin/fuser -k -SIGHUP 6543/tcp
for h in $(cat st.ssh);do echo "$h:" && ssh -p 5222 $h 'sed -i "s/Port 6543/Port 22/g" /opt/ssh/etc/sshd_config && /usr/sbin/fuser -k -SIGHUP 6543/tcp';done
查看对应的端口上是否有进程在侦听,检查22与5222是否都存在,5222是不是由系统的sshd所侦听
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/usr/sbin/fuser 5222/tcp';done
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/usr/sbin/fuser 22/tcp';done
都确认OK后,将5222停止并将原sshd服务从系统中移除,防止因机器重启而拉起老的ssh服务
/usr/sbin/fuser -k -SIGHUP 5222/tcp && systemctl stop sshd.service && systemctl disable sshd.service
for h in $(cat st.ssh);do echo "$h:" && ssh $h '/usr/sbin/fuser -k -SIGHUP 5222/tcp && systemctl stop sshd.service && systemctl disable sshd.service';done
至此完成。
configure时可能遇到的问题
configure: error: PAM headers not found
典型的缺少依赖包,安装之
yum install pam-devel libedit-devel -y
在有机器上报:
/var/empty must be owned by root and not group or world-writable.
这个系权限问题,将组的可写权限移除后解决此问题。
在CentOS 7上制作rpm包升级openssh到9.8p1
2024年7月1日,OpenSSH暴露了一个远程代码执行漏洞(CVE-2024-6387,又被称为regreSSHion),影响版本8.5p1<=版本<9.8p1,该漏洞影响基于glibc的Linux系统上的OpenSSH Server。由于OpenSSH服务器 (sshd) 中的信号处理程序竞争问题,未经身份验证的攻击者可以通过恶意构造的SSH客户端请求,利用此漏洞在OpenSSH服务器上以root身份执行任意代码。该漏洞利用复杂但影响面很广,今天来分享下如何升级及如何制作它的rpm包。为什么快一个月才写这篇文章,因为目前的poc需要大量的时间才能rce,需要不断的去尝试,而且成功率只有一半所以耗时比较久,影响范围并不是那么大,但是以防万一还是建议进行升级。
1、开启备用的登录通道
需要开启telnet或另外一个端口的sshd,因为要防止升级失败,还能通过备用通道远程登录系统进行应急处理。同时还要对主机的防火墙规则进行梳理,防止被阻止及root是否能直接登录主机。或使用salt工具来直接进行远程被动管理。
2、制作RP包
1. 安装rpm包制作工具
yum install rpm-build rpmdevtools rpmdev* gcc gcc-c++ make autoconf rpmlint rpmrebuild -y
rpmdev-setuptree
在"/root"目录(非root用户为"/home/用户名"目录)下多了一个 rpmbuild 的文件夹,目录结构如下:
[root@freeoa openssh-9.8p1]# ls -lh ~/rpmbuild/
total 0
drwxr-xr-x 2 root root 6 Jul 27 16:31 BUILD
drwxr-xr-x 2 root root 6 Jul 27 16:31 RPMS
drwxr-xr-x 2 root root 6 Jul 27 16:31 SOURCES
drwxr-xr-x 2 root root 6 Jul 27 16:31 SPECS
drwxr-xr-x 2 root root 6 Jul 27 16:31 SRPMS
目录说明如下:
目录 | 宏代码 | 名称 | 功能 |
~/rpmbuild/BUILD | %_builddir | 构建目录 | 源码包被解压至此,并在该目录的子目录完成编译 |
~/rpmbuild/RPMS | %_rpmdir | 标准 RPM 包目录 | 生成/保存二进制 RPM 包 |
~/rpmbuild/SOURCES | %_sourcedir | 源代码目录 | 保存源码包(如 .tar 包)和所有 patch 补丁 |
~/rpmbuild/SPECS | %_specdir | Spec 文件目录 | 保存 RPM 包配置(.spec)文件 |
~/rpmbuild/SRPMS | %_srcrpmdir | 源代码 RPM 包目录 | 生成/保存源码 RPM 包(SRPM) |
2. 下载源码包到对应目录
cd ~/rpmbuild/SOURCES/
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz
wget https://src.fedoraproject.org/repo/pkgs/openssh/x11-ssh-askpass-1.2.4.1.tar.gz/8f2e41f3f7eaa8543a2440454637f3c3/x11-ssh-askpass-1.2.4.1.tar.gz
3. 生成spec文件模板,并修改相关内容
SPECS 下是RPM包的配置文件,是RPM打包的“图纸”,这个文件会告诉rpmbuild命令如何去打包。“宏代码”这一列就可以在SPEC文件中用来代指所对应的目录,类似于编程语言中的宏或全局变量。
解压下好的openssh软件包源码,复制出官方提供的spec文件,rpm-build需要根据这个文件来制作rpm包:
cd ~/rpmbuild/SOURCES
tar -zxvf openssh-9.8p1.tar.gz
cp openssh-9.8p1/contrib/redhat/openssh.spec ~/rpmbuild/SPECS/openssh-9.8p1.spec
cd ~/rpmbuild/SPECS/
在SPEC文件中,各个阶段说明如下:
阶段 | 读取的目录 | 写入的目录 | 具体动作 |
%prep | %_sourcedir | %_builddir | 读取位于 %sourcedir 目录的源代码和 patch。之后,解压源代码至%builddir 的子目录并应用所有 patch。 |
%build | %_builddir | %_builddir | 编译位于 %_builddir 构建目录下的文件。通过执行类似 ./configure && make的命令实现。 |
%install | %_builddir | %_buildrootdir | 读取位于 %builddir 构建目录下的文件并将其安装至 %buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。 |
%check | %_builddir | %_builddir | 检查软件是否正常运行。通过执行类似 make test 的命令实现。 |
bin | %_buildrootdir | %_rpmdir | 读取位于 %buildrootdir 最终安装目录下的文件,以便最终在 %rpmdir 目录下创建 RPM 包。在该目录下,不同架构的 RPM 包会分别保存至不同子目录, noarch 目录保存适用于所有架构的 RPM 包。这些 RPM 文件就是用户最终安装的 RPM 包。 |
src | %_sourcedir | %_srcrpmdir | 创建源码 RPM 包(简称 SRPM,以.src.rpm 作为后缀名),并保存至%_srcrpmdir 目录。SRPM 包通常用于审核和升级软件包。 |
默认openssh源码中是没有ssh-copy-id相关参数的,如果直接编译安装,会发现安装后没有ssh-copy-id命令,因此如果需要用到该命令,需要修改编译参数控制文件openssh-9.8p1.spec:
......
%install
......
install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd
#添加如下行内容,281行处
install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT/usr/bin/ssh-copy-id
......
%attr(0755,root,root) %{_bindir}/ssh-keygen
#添加如下行内容,362行处
%attr(0755,root,root) %{_bindir}/ssh-copy-id
4. 安装相关依赖包
yum -y install zlib zlib-devel perl gcc gcc-c++ autoconf pam-devel gtk2-devel imake krb5-devel libXt-devel make tree
5. 测试SPEC 文件是否有错误
rpmlint openssh-9.8p1.spec
# 这里可能会报没法下载x11-ssh-askpass-1.2.4.1.tar.gz,可以不管它,因为我们前面已经手动下载到SOURCES里面了
6. 构建RPM 包
rpmbuild -bb openssh-9.8p1.spec
如果成功,RPM 会保存至 ~/rpmbuild/RPMS:
3、升级
1. 查看当前版本及openssh相关的包
ssh -V
rpm -qa | grep openssh
2. 备份
cp -ar /etc/ssh/ /etc/ssh_7.4p1
cp -p /etc/pam.d/sshd /etc/pam.d/sshd_7.4p1
3. 安装
cd /root/rpmbuild/RPMS/x86_64
yum localinstall openssh* -y
rpm -qa | grep openssh
使用备份文件恢复/etc/pam.d/sshd文件内容
mv /etc/pam.d/sshd /etc/pam.d/sshd_9.8p1
mv /etc/pam.d/sshd_7.4p1 /etc/pam.d/sshd
5. 修改sshd_config,默认root无法登录,如果本来就要求root不能登录的情形可以忽略
PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication yes
UsePAM yes
6. 重启sshd服务并检查服务
systemctl restart sshd
systemctl status sshd
ssh -V
7. 远程登录测试
8. 测试没有问题可以关闭备用通道
提供一个看本局域网内所有机器上指定端口的sshd的版本信息的Perl脚本(多线程)
use v5.20;
use threads;
use Data::Dumper;
use Thread::Queue;
use IO::Socket::INET;
my $q=Thread::Queue->new();
my @addres=(1..254);
my @hosts=map "10.206.xx.$_",@addres;
my ($thread_num,@workers)=(9);
#准备线程的运行
for(1..$thread_num){
push @workers,async{
while(defined(my $ip=$q->dequeue())){
my $tid=threads->self->tid();
worker($ip);
}
};
}
sub worker{
my $host=shift;
# create a connecting socket
my $socket = new IO::Socket::INET (PeerHost => "$host",PeerPort => '22',Proto => 'tcp',Timeout=>'1');
unless($socket){warn "cannot connect to $host by $!" && return;}
# data to send to a server
my $req = 'hi.';
my $size = $socket->send($req);
# notify server that request has been sent
# receive a response of up to 1024 characters from server
my $response = "";
$socket->recv($response, 1024);
print "$host:$response";
$socket->close();
}
$q->enqueue($_) for @hosts; # Send work
$q->end() for @workers; # Tell workers they're done.
$_->join() for @workers; # Wait for the workers to finish.
因开启SELinux导致更换端口后不能成功重启的问题排查
sshd[16592]: error: Bind to port 6543 on 0.0.0.0 failed: Permission denied.
sshd[16592]: error: Bind to port 6543 on :: failed: Permission denied.
sshd[16592]: fatal: Cannot bind any address.
查看一下selinux的状态
# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 21
Policy from config file: targeted
要查看ssh允许的端口
# semanage port -l | grep ssh
ssh_port_t tcp 22
允许ssh服务运行在6543端口上
# semanage port -a -t ssh_port_t -p tcp 6543
再次查看设置是还实现
# semanage port -l | grep ssh
ssh_port_t tcp 6543, 22
再通过systemctl指令重启ssh服务会发现能正常重启了
sshd[27291]: Received signal 15; terminating.
sshd[27367]: Server listening on 0.0.0.0 port 6543.
sshd[27367]: Server listening on :: port 6543.