使用OpenSSH證書認證

wyzsk發表於2020-08-19
作者: r00tgrok · 2014/03/11 15:22

0x00 摘要


2010年三月,ssh證書認證悄然地包含到了OpenSSH5.4中。到了2014年,很多人對ssh證書依舊相當模糊,既沒有得到廣泛的理解,也沒有得到廣泛的使用。對於這樣一個問題,我們可能會認為它實施起來要不是很難,就是很複雜。實際上這樣做既不難,也不復雜,只是它沒有得到較好的文件化的描述。 

本文的目標是以一種實際的方式向各位展示使用和管理ssh證書認證有多容易,無論是較小的還是較大的環境。

本文的建立用於解答筆者日常中遇到的一些ssh證書認證的問題,當然還增添了在學習過程中發現的一些東西。本文內容中也許會有點小差錯,某些特性也沒有提到,歡迎各位指正。

0x01 基本知識


本文假設你已經瞭解:

基本的Unix/Linux伺服器管理

SSH管理,包括但不限於:

a) 金鑰生成
b) SSH公鑰認證
c) 使用SSH代理
d) 使用口令加密金鑰

基本的安全概念如:

不要直接以root身份登陸

0x02 SSH證書介紹


證書是已有的ssh公鑰認證系統的擴充套件,可被應用於任何已有的公鑰和私鑰對,也可以用於任何當前ssh支援的認證方法。

儘管(SSH證書認證)基於公鑰認證,它同時也被設計來簡化多臺伺服器之間金鑰管理的複雜性。證書免除了對已知主機和經授權使用者檔案的需要,如果實現合理的話,只許更少的人力便能複製全部功能。

由於證書認證是公鑰加密的一個擴充套件,它可以與OPenSSH支援的任意金鑰型別和金鑰大小的ssh2協同使用。這意味著如果你當前的OpenSSH支援的話,RSA、DSA、EC都能使用。方便起見,本文將使用預設的RSA-1024。

Tips:有些較老的作業系統雖然使用OpenSSH5.4或更高的版本,但是還是不支援EC。

0x03 證書 VS. 公鑰


常規的公鑰認證和證書認證之間有幾點較大的不同,最大的不同就是證書驗證上。

與其他公鑰證書標準不同

SSH證書相比其他證書格式如x509、SSL中使用的PEM更為簡單

a) 沒有證書鏈,只有一個CA
b) 沒有可疑的的商業簽名授權(authority)
c) 除了CA簽名外沒有可信模式

主機認證

操作 公鑰認證 證書認證
認證未知主機 初始登陸時詢問使用者是否接受主機秘鑰 驗證CA簽發的主機證書
認證已知主機 將金鑰和使用者的已知主機檔案對比 驗證CA簽發的主機證書
替換已知主機的金鑰 a) 入口必須從使用者的已知主機檔案中刪除 b) 使用者登入時會被問及是否接受新的主機秘鑰 驗證CA簽發的主機證書
撤銷金鑰/證書 [email protected] [email protected]

使用證書認證的好處

a) 使用者可以認證之前沒有登入過的主機
b) 無需再分發或管理已知的已知主機檔案(例:puppet)
c) 可以無需使用者干預實現伺服器替換及金鑰再生成
d) 除非什麼地方出錯了,使用者在工作場合再也不會收到接受伺服器金鑰的提示
e) 透過搜尋未簽名的主機金鑰可以發現不一致的主機

使用者認證

操作 公鑰認證 證書認證
認證 使用者的公鑰來自每個伺服器主機使用者經授權的金鑰檔案 檢查使用者證書是否由CA簽名
過期金鑰/證書 不做強制 過期時間由管理員在簽名時設定
登入使用者名稱 伺服器上的目標使用者的公鑰置於每個使用者目錄下的authorized_keys檔案中 使用者名稱可在簽名時新增到證書中,也可由每個伺服器上的AuthorizedPrinciples檔案控制
限制(埠轉發、強制命令等) 可以在authorized_keys檔案中(可被使用者編輯),可在每個伺服器sshd_config的匹配使用者/組塊中 可在簽名時加入證書中,可在每個伺服器sshd_config的匹配使用者/組塊中,可在每個伺服器”經授權的規則”中新增
撤銷金鑰/證書 可新增到每個伺服器的RevokedKeys檔案中或從伺服器上每個受影響的authorized_keys檔案移除 每個伺服器上將證書新增到”RevokedKeys”檔案中
替換使用者的證書 伺服器上authorized_keys檔案必須可被編輯 將舊證書新增到伺服器上已撤銷的金鑰檔案或簽名新的證書

使用證書認證的好處

a) 證書過期時間可由管理員在簽名時設定,強制實施輪轉策略 
b) 無需跨越多臺主機管理已授權的證書 
c) 不用擔心惡意使用者編輯或新增內容到未管理的經授權檔案 
d) 在簽名時更容易限制某些使用者的許可權 
e) 無需從已授權金鑰檔案中移除已吊銷的金鑰 
f) 證書籤名時可以限制使用者使用指定的使用者名稱 

0x04 讓它工作起來


實現ssh證書認證要比SSL證書容易得多,最難的地方是決定簽名使用者和伺服器是使用單個CA金鑰還是使用兩個CA金鑰——伺服器和使用者各一個

我們推薦使用兩個獨立的金鑰用於簽名的使用者和伺服器,以便讓不同的角色來管理每一個功能:例如,一個系統管理員可以登入伺服器金鑰,而安全管理員可以登入該使用者的金鑰。

下面的例子中伺服器和使用者使用各自的證書授權

伺服器授權

啟用伺服器授權僅需4個步驟

1. 建立伺服器CA

在你的證書授權伺服器上執行下列命令:

#!bash
~ $ # Lets start with good organization
~ $ mkdir -p ssh_cert_authorita/server_ca
~ $ cd ysh_cert_authority/server_ca/

~/ssh_cert_authority/server_ca $ # Now lets generate our server certificate authority keypair
~/ssh_cert_authority/server_ca $ ssh-keygen -f server_ca -C "companyname_server_ca"
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
wour identification has been saved in server_ca.
Your public key has been saved in server_ca.pub.
The key fingerprint is:
21:f6:9f:5d:ec:75:2e:df:c0:6b:5e:9d:5b:97:d8:19 "companyname_server_ca"

~/ssh_cert_authority/server_ca $ # The resulting files
~/ssh_cert_authority/server_ca $ ls -l
total 8
-rw------- 1 username username 1675 Aug 16 14:12 server_ca
-rw-r--r-- 1 username username  409 Aug 16 14:12 server_ca.pub

Tips:強烈建議不僅使用密碼,還要使用強密碼。任何用這個金鑰簽名的人都能新增受信任的伺服器訪問到你的網路。

2. 簽名主機金鑰

既然證書認證是公鑰認證的一個擴充套件,你可以使用已有的

/etc/ssh/ssh_host*key.pub

ssh主機金鑰。舉例來說,任何型別的ssh主機金鑰都可以。

在你的證書授權伺服器上執行如下命令:

#!bash
~/ssh_cert_authority/server_ca $ # 為複製主機金鑰和證書留個地方
~/ssh_cert_authority/server_ca $ mkdir -p host_certs
~/ssh_cert_authority/server_ca $ cd host_certs

~/ssh_cert_authority/server_ca/host_certs $ # 從主機下載主機金鑰
~/ssh_cert_authority/server_ca/host_certs $ scp -rp example.host.net:/etc/ssh/ssh_host_rsa_key.pub example.host.net.pub
ssh_host_rsa_key.pub                                                                   100%  396     0.4KB/s   00:00    

~/ssh_cert_authority/server_ca/host_certs $ # 簽名主機金鑰
~/ssh_cert_authority/server_ca/host_certs $ ssh-keygen -s ../server_ca -I example.host.net -h -n example.host.net,96.126.102.173,2600:3c01::f03c:91ff:fe69:87a2 example.host.net.pub 
Signed host key example.host.net-cert.pub: id "example.host.net" serial 0 for example.host.net,123.45.67.89,2600:dead:beef:cafe:::87a2 valid forever

~/ssh_cert_authority/server_ca/host_certs $ # 結果檔案
~/ssh_cert_authority/server_ca/host_certs $ ls -l
total 8
-rw-r--r-- 1 username username 1430 Aug 16 14:19 example.host.net-cert.pub
-rw-r--r-- 1 username username  396 Jul 14 20:19 example.host.net.pub

~/ssh_cert_authority/server_ca/host_certs $ # 將證書考回伺服器
~/ssh_cert_authority/server_ca/host_certs $ scp -rp example.host.net-cert.pub [email protected]:/etc/ssh/ssh_host_rsa_key-cert.pub
example.host.net-cert.pub                                                           100% 1430     1.4KB/s   00:00

Tips:

保留CA的所有公鑰及證書,如果你需要撤銷它們,最好複製一份 

建立伺服器證書時,注意 –l 、–h、 –n 選項的用法 

1) -n 選項只能指向相關的主機名、IP地址,空格、萬用字元或任意名字會導致可互換的伺服器證書 
2) -l 選項可以是用於標識這個證書的任意文字,而且你沒必要使用和上面同樣的格式 
3) -h 選項標明證書為主機證書

3. 改變伺服器配置

HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

儲存/etc/ssh/sshd_config儲存完畢後,重啟sshd

4. 客戶端配置改變

複製server_ca.pub中的文字,進入你的~/.ssh/known_hosts(或/etc/ssh/known_hosts)檔案,參考:

#!bash
@cert-authority *.host.net,123.45.67.* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVifNRc+EN4b9g/ygWRCIvV1qw0aR33qzkutIA6C3MzHidaXe6tO4Q35YqrP2UUhOdcl2g8nO7BNSSHkjrFyEnyNqkpgHYcDzUdpE6XGS6rNcjrmLajf1CRvUBvFD0ceu//z6HL1dpE347AHSZbFxHT6NdhscdEd/Bd5c1aVyS+dUdiGX4U9YdgTN2lM8zQy5rJo+siFyHmtqXh1ZVBBC+VBF6ZPzMkxvkJmAp4eWCQJOZLIybcNZlyuXrs1bXV0X0ZIIL2j/gYC2gJPO1FUTKRcqzo/fQ/m6hAhxMMpTTgI92FiE/QOfOk5+MmgfTOqsF0us2TJ5mrSIE9o/3DQsj "companyname_server_ca"

Tips:

a) 刪除 known_host 中與”example.host.net”相關的host
b) 該檔案的格式遵循標準的known_hosts格式,但要注意萬用字元匹配整個域和IP地址範圍。

5. 測試伺服器認證

#!bash
~ $ ssh -v [email protected]
...
debug1: Server host key: RSA-CERT 39:aa:3f:bb:eb:24:11:93:15:b1:63:2f:de:ad:be:ef
debug1: Host 'example.host.net' is known and matches the RSA-CERT host certificate.
...

使用者認證

使用者認證不會比伺服器認證更難

1. 建立使用者CA

在你的證書授權伺服器上執行下列命令:

#!bash
~ $ # Lets start with good organization
~ $ mkdir -p ssh_cert_authority/user_ca
~ $ cd ssh_cert_authority/user_ca

~/ssh_cert_authority/user_ca $ # 生成我們的伺服器證書授權金鑰對
~/ssh_cert_authority/user_ca $ ssh-keygen -f user_ca -C "companyname_user_ca"
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in user_ca.
Your public key has been saved in user_ca.pub.
The key fingerprint is:
90:67:8a:ed:b6:53:0a:bd:06:f0:71:ce:fb:89:b9:3e "companyname_user_ca"

~/ssh_cert_authority/user_ca $ # 結果檔案
~/ssh_cert_authority/user_ca $ ls -l
total 8
-rw------- 1 username username 1679 Aug 16 18:14 user_ca
-rw-r--r-- 1 username username  407 Aug 16 18:14 user_ca.pub

~/ssh_cert_authority/user_ca $ # 把user_ca.pub複製到伺服器上
~/ssh_cert_authority/user_ca $ scp -rp user_ca.pub [email protected]:/etc/ssh
user_ca.pub                                                                            100%  407     0.4KB/s   00:00

Tips:強烈建議不僅使用密碼,還要使用強密碼。任何用這個金鑰簽名的人都能訪問你網路中所有伺服器上的任意使用者。

2. 簽名使用者金鑰

讓一個使用者建立一個ssh公鑰集,並獲得他們公鑰的複製

恢復使用者公共SSH金鑰的複製,執行如下命令:

#!bash
~/ssh_cert_authority/user_ca $ # 我們需要一個地方存放簽名的證書
~/ssh_cert_authority/user_ca $ mkdir -p user_certs
~/ssh_cert_authority/user_ca $ cd user_certs/

~/ssh_cert_authority/user_ca/user_certs $ # 以使用公鑰為例
~/ssh_cert_authority/user_ca/user_certs $ cp ~/.ssh/id_rsa.pub username.pub

~/ssh_cert_authority/user_ca/user_certs $ # Sign the key
~/ssh_cert_authority/user_ca/user_certs $ ssh-keygen -s ../user_ca -I user_full_name -n root,loginname username.pub 
Signed user key username-cert.pub: id "user_full_name" serial 0 for root,loginname valid forever

~/ssh_cert_authority/user_ca/user_certs $ # 結果檔案
~/ssh_cert_authority/user_ca/user_certs $ ls -l
total 8
-rw-r--r-- 1 username username 1525 Aug 16 22:01 username-cert.pub
-rw------- 1 username username  411 Aug 16 22:00 username.pub

~/ssh_cert_authority/user_ca/user_certs $ # 複製證書到使用者的~/.ssh/資料夾下
~/ssh_cert_authority/user_ca/user_certs $ cp username-cert.pub ~/.ssh/id_rsa-cert.pub

Tips:

保留CA的所有公鑰和證書,如果你需要撤銷它們,最好複製一份 
當建立伺服器證書時,你不能否認–l、–n 選項的使用 

a) -n 選項只能指向相關的登陸使用者名稱,空格、萬用字元名字會允許任何有效使用者賬戶的登入,除非在服務端有其他的嚴格限制。在本例中,使用者名稱使用root和loginname
b) -l 選項可以是用於標識這個證書任意文字,而且你沒必要使用和上面一樣的格式

3. 伺服器配置改變

在你想啟用證書認證的每臺伺服器上將如下程式碼新增至/etc/ssh/sshd_config

TrustedUserCAKeys /etc/ssh/user_ca.pub

儲存sshd_config檔案,重啟sshd

4. 測試使用者認證

從服務上所有的經授權金鑰檔案中刪除使用者公鑰

執行如下命令:

#!bash
~ $ ssh -v [email protected]
...
debug1: identity file /home/username/.ssh/id_rsa-cert type 4
debug1: Offering RSA-CERT public key: /home/username/.ssh/id_rsa
debug1: Server accepts key: pkalg [email protected] blen 1101
...

另外,如果你開啟了除錯記錄,你會看到如下日誌:

#!bash
Jul 18 23:22:03 localhost sshd[9603]: debug1: list_hostkey_types: ssh-rsa,[email protected] [preauth]
Jul 18 23:22:03 localhost sshd[9603]: Accepted certificate ID "user_username" signed by RSA CA d2:c0:6c:08:2b:e4:b4:f2:cd:56:22:66:de:ad:be:ef via /etc/ssh/user_ca.pub

0x05 更進一步


上述步驟是證書認證的基礎,接下來我們會涵蓋一些更細節的特性。

撤銷金鑰和證書

授予訪問你的伺服器很棒,但是你必須要有權利撤銷這種訪問

下面的方法同樣適用於公鑰認證,目前它們是撤銷ssh證書的唯一方式

1. 撤銷使用者金鑰

啟用使用者取消功能,將如下程式碼新增至你伺服器的/etc/ssh/sshd_config

#!bash
RevokedKeys /etc/ssh/ssh_revoked_keys

然後輸入如下命令:

#!bash
~ $ # 如果檔案不存在且對sshd不可讀,**all** 使用者將沒有訪問許可權
~ $ sudo touch /etc/ssh/ssh_revoked_keys
~ $ sudo chmod 644 /etc/ssh/ssh_revoked_keys.

一旦完成,重啟sshd

當需要從伺服器撤銷使用者訪問許可權時,簡單地新增其公鑰或證書到/etc/ssh/ssh_revoked_keys中。檔案格式同authorized_keys金鑰類似,一個金鑰或證書佔一行

#!bash
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDL8HShSFKdY3Tox9U+gUotTFlRedPxI5zSrU6KiZEXA8i+37BtB0yp502q3Dx1MmXBF8Pqa+xEQ9DOgtragDwX0V7ieOjvRSB83w2Orj9cdMj8U6WluU2T+QlD2JtVmOp0Skg4k3AENIN9J0rmnxvmuCZa2G5f+6DGp/pW5kk9FfNv1xaAOgy3yfExD2w5cEHZfztajbTuCE6z9aNxU96ZHvXdV6Z8M3xkkea6IUU3XCyg+lB/qSq+KoBoByzwZSJ6BfA7x63okq57K6XsPp4GuVukq0OmDk9ZLpqmeC8esWhniA+2DwmjdaFa1k9K/bpCy4mVLhqTgwkU9u8rxaCd [email protected]
[email protected] [email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected][email protected]rI+pD9mv7qLU3h22JvQUKnuWNvdJJuQATZ [email protected]

Tips:

a) 這阻斷了系統範圍公鑰和證書的使用
b) 公鑰更為理想化,因為它們更小,除了會阻斷證書認證還會阻斷公鑰
c) 這裡證書同樣能工作良好,但是如果它在authorized_keys檔案中它不會阻斷公鑰


Jul 19 00:27:26 localhost sshd[11546]: error: WARNING: authentication attempt with a revoked RSA-CERT key 6d:59:82:70:2b:93:dc:57:a6:c6:1f:64:de:ad:be:ef

2. 撤銷伺服器金鑰

伺服器金鑰得從使用者的已知主機檔案中撤銷,或者在/etc/ssh/known_hosts使用:

#!bash
@revoked * ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc9wlKYUzWZcfvPOa0L+h6Wbb/k9yJgXbnqa3VF+ucdwmBSiT3zBMAjqjFMnN3MuI4oig3SqkIXKPWn0QgFoV4d3G4opzs/OdZ6WLyxLwYQBggUQDg4QhKuHDltIR/BMxYlhB20ngmkaiBiK+Q4ThFRpW7FElOsuZ3rgJq559PgkFeFMY06oyzUMaSshFM84U/1zrVL4BgdnZBcJn018psem5kSkd0Gxm+ao1TuEnMGeArVMFiG9Hq1o2E+QGp1euE4YYQtR533fyZ8BSTE9ThLkmTXgU31dn1irFatBrBENm7TnIVmNT410NqV5J9zDME4NAnuEVwNWtq65rZkgut [email protected]

Tips:

a) 萬用字元會阻止主機金鑰被任何主機使用 
b) 上面的情況中,公鑰和證書都能工作,不過公鑰更小且更有效 
c) 當和個別已知主機入口一起工作時,簡單地刪除一個入口並不會阻止金鑰被再次使用 

示例:

#!bash
~ $ ssh example.host.net
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@       WARNING: REVOKED HOST KEY DETECTED!               @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The RSA host key for example.host.net is marked as revoked.
This could mean that a stolen key is being used to impersonate this host.
RSA host key for example.host.net was revoked and you have requested strict checking.
Host key verification failed.

證書控制

簽名一個證書時,管理員可以直接實行證書控制,在沒有重簽名的情況下證書不能被改變

1. 證書過期

大多陣列織使用密碼過期策略,許多情況下需求密碼和證書過期,遺憾的是目前僅有特設方法執行ssh金鑰輪換。

使用證書,一個過期日期在簽名時會載入到證書中,可以使用ssh時間格式-V選項完成

#!bash
~/ssh_cert_authority/user_ca/user_certs $ # Expiration in 52 weeks
~/ssh_cert_authority/user_ca/user_certs $ ssh-keygen -s ../user_ca -I user_full_name -n root,loginname -V +52w username.pub

~/ssh_cert_authority/user_ca/user_certs $ # Expiration in 180 days
~/ssh_cert_authority/user_ca/user_certs $ ssh-keygen -s ../user_ca -I user_full_name -n root,loginname -V +180d username.pub

2. 登入名

正如簽名提到的,可以使用-n選項強制使用證書中的登入名和伺服器名

對使用者來說,這限制了使用者在遠端伺服器上指定的登入名,一般來說,這應該是一個單使用者名稱,但是在一些環境中可能需要多個使用者名稱

下面的例子允許單個證書上的多個登入名:

#!bash
~/ssh_cert_authority/user_ca/user_certs $ ssh-keygen -s ../user_ca -I user_full_name -n loginname,anothername,thirdname username.pub

3. 選項(僅限使用者證書)

對於使用者證書

對使用者證書而言,簽名時可以直接構建好幾個選項到證書中。一般來說,這些選項運用於/etc/sshd_config或經授權的金鑰檔案中,這些選項是:

a) clear:假設沒有預設選項 
b) force-command=(command):強制遠端命令執行 
c) 預設許可的:代理轉發/無代理轉發 
d) 預設許可的:埠轉發/無埠轉發 
e) 預設許可的:pty/無pty 
f) 預設許可的:permit-user-rc/no-user-rc 
g) 預設許可的:x11轉發/無x11轉發 
h) 源地址=(地址列表):限制源地址,這些地址中的證書為有效 

示例:

#!bash
~/ssh_cert_authority/user_ca/user_certs $ ssh-keygen -s ../user_ca -I user_full_name -n login \
  -O clear \ # Clear all default options, including forwarding of all kinds
  -O force-command=/some/specific/command \ # force execution of a specific command
  -O source-address=10.22.72.0/24 \ # limit logins from specific source addresses
  username.pub

上面的例子限制了只能在特定的伺服器上自動化批處理,不允許pty,轉發,並強制特定的命令

0x06 已知的問題


證書版本問題

隨著OpenSSH6.x的釋出,證書的更新導致和OpenSSH 5.x之間存在相容性問題

OpenSSH6.x生成的證書在OpenSSH 5.x上需要使用選項”-t v00”才能執行,例如:

#!bash
$ ssh-keygen -t v00 -s ca_key -I key_id host_key.pub

OpenSSH 6.x似乎向後相容OpenSSH 5.x生成的證書

SSH客戶端相容性

除了OpenSSH,如果有的話,僅有少數客戶端支援基於認證的證書

儘管大多數常見或不常見的作業系統都執行OpenSSH,也還是有使用其他客戶端的。舉例來說,Windows上非常流行的Putty,它至今都不支援證書認證。許多使用ssh的商業應用不支援證書認證,例如Rapid7的Nexpose

因此,如果可以的話,有些環境可能會比較難以強制實行只基於認證的證書

CA金鑰安全

集中化的金鑰管理簡化了認證管理流程,不幸的是這同時也簡化了攻擊面,攻擊者只許獲得CA金鑰的管理就能獲得對全網的訪問

因此,CA金鑰的管理必須處於高安全等級,如果可能的話,將它們儲存在網路無法訪問的地方,並千萬千萬確保它們被加密了

0x07 參考資料


本文根據收集來的OpenSSH手冊資訊進行組織,它們可能會更詳盡而且內容以後也會比本文更新

sshd_config – OpenSSH SSH daemon configuration file

sshd – OpenSSH SSH daemon

ssh-keygen – authentication key generation, management and conversion

原文:Using OpenSSH Certificate Authentication

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章