自己署名証明書の検証


サードパーティ製のWebサービスにインタフェースする際には、検証エラーを引き起こす自己署名SSL証明書を扱う必要があります.つの回避策はそれらのエラーを抑えることです.(例えば、curlツールには' insecure 'フラグがあります.しかし、Smarkingでは、このような証明書を検証し、中間攻撃の人間からのデータ通信を保護する方法を見つけました.
従来、Webブラウザは、SSL証明書を検証する公開鍵インフラストラクチャ(PKI)に依存しています.すべての証明書は別の(署名)証明書によって署名されます.署名証明書は別のものによって署名されなければなりません、信頼された証明書の終わりの鎖で.このリンクを使用すると、Webサーバーのオペレータがウェブブラウザを更新するために自分のウェブサイトにビジターを必要とせずに新しいSSL証明書に切り替えることができます.あるいは、ブラウザが署名チェックインする必要がないように、彼のユーザに特定の証明書を信頼するよう頼むことができました.
SSL証明書は、それの中でそれをウェブサーバの公開鍵を運びます.概念的なレベルでは、公開鍵の信頼性は、ブラウザとサーバーの間で認証されたDiffie - Hellmanキー交換を確立することができるものです.したがって、正しい公開鍵であることを確認することができれば、証明書を「検証」したでしょう.しかし、長い公開鍵を検証するのではなく、通常、はるかに短いチェックサムを確認することができます.全体の証明書のチェックサムは指紋と呼ばれています、そして、それは常にHEXコードのコロンで区切られたリストとしてフォーマットされます.例えば、証明書のSHA - 256指紋https://google.com:
14:71:16:87:6D:F6:76:8E:98:E5:66:62:70:64:F1:0F:F8:0F:87:39:B8:55:4C:47:26:22:DF:FA:7D:1D:A5:FE
ウェブサイトの証明書の詳細を取得するには、ブラウザのURLバーのロックアイコンをクリックし、SSL証明書の詳細を検査します.また、以下のシェルスクリプトを使用することもできます.
#!/bin/bash
HOST=example.com
PORT=443
PROXY=1.2.3.4:8888

# If your environment does not require a HTTP proxy, delete the '-proxy $PROXY' parameter below
echo quit | openssl s_client -showcerts -servername $HOST -connect $HOST:$PORT -proxy $PROXY > result.txt
出力ファイルresult.txt PEM形式とメタデータの証明書を含みます.PEM形式はbase 64を使ってASCIIにエンコードされたバイナリデータから成ります.
-----BEGIN CERTIFICATE-----
<certificate encoded in base64 encoding>
-----END CERTIFICATE-----
あなたは、フィードresult.txt 次のコマンドに、証明書の指紋を計算します.(The openssl ツールは、入力ファイルで見つかった最初の証明書を使用し、他のすべてを無視します.
$ openssl x509 -noout -fingerprint -sha256 -inform pem -in result.txt
上記のコマンドは-sha256 スイッチは、32バイトである指紋の長さを決定します.したがって、指紋の長さは、指紋を得るために使用されるアルゴリズムを識別します.
ここでは、指紋で証明書を確認できる3つの方法があります.

メソッド1.Pythonを使う
指紋による証明書の検証は、箱によってurllib3 ライブラリを使用assert_fingerpint パラメータ
import urllib3
from urllib.parse import urlparse

def http_get_request(url, fingerprint):
  parsed_url = urlparse(url)
  host = parsed_url.netloc
  path = parsed_url.path
  pool = urllib3.HTTPSConnectionPool(host, assert_fingerprint=fingerprint)
  response = pool.urlopen('GET', path)
  return response

response = http_get_request('https://example.com/a/b/c', '14:71:...')
print(response.data)
指紋オプションが設定することに注意してくださいHTTPSConnectionPool それから、それはウェブサイトに対する一連の質問をするために使用されることができました、そのように、各々の質問が証明書の指紋を確認するでしょう.
Pythonのrequests ライブラリの認証指紋認証もサポートしていますurllib3 図書館.を返します.HTTPSConnectionPool 上で議論されたオブジェクトSession::mount() これにより、特定のベースURLにカスタムアダプタを設定できます.これをまとめると、次のコードがあります.
from urllib.parse import urlparse

def create_fingerprint_session(url, fingerprint):
  host = urlparse(url).netloc
  s = requests.Session()
  s.verify = False
  s.mount('https://{}/'.format(host), FingerprintAdapter(fingerprint))

session = create_fingerprint_session(('https://example.com/a/b/c', '14:71:...')
response = session.get(url)
print(response.text)
注意verify 設定はfalse、requests ライブラリはSSL証明書を従来の方法で署名鎖とドメイン名で検証しようとします.
(verify パラメータは、PEM形式の信頼された証明書の連結リストを含む証明書ファイルの場所に設定することもできます.しかしながら、自己署名証明書はカスタム認証局(CA)によって署名されます、しかし、CAの証明書は通常私たちに知られていません.したがって、このオプションは使用しませんverify to False .)
現在残っているのはFingerprintAdapter . 最も速い方法はサブクラスHTTPAdapter クラスを作成し、HTTPPoolConnection オブジェクトを含めるassert_fingerprint オプション:
from requests.adapters import HTTPAdapter

class FingerprintAdapter(HTTPAdapter):
  """
  A TransportAdapter that allows to verify certificates by fingerprint
  """
  def __init__(self, fingerprint, *args, **kwargs):
    self._fingerprint = fingerprint
    HTTPAdapter.__init__(self, *args, **kwargs)

  def init_poolmanager(self, *args, **kwargs):
    kwargs['assert_fingerprint'] = self._fingerprint
    return super().init_poolmanager(*args, **kwargs)

  def proxy_manager_for(self, *args, **kwargs):
    kwargs['assert_fingerprint'] = self._fingerprint
    return super().proxy_manager_for(*args, **kwargs)
要するに集合verify=True 信頼されたCAによって署名された証明書で働くときverify=False とマウントFingerprintAdapter 指紋による自己署名証明書の検証検証は、指紋の値を変更し、セキュリティエラーを観察することによって動作していることをテストします.

法線φ2:サイト幅
どのような場合は、他のツールを使用したい場合は、Pythonの他に、Webサイトのクエリを署名して署名した自己署名証明書?サイト全体の解決策は、自己署名証明書を信頼できる証明書のリストに追加することです.
しかし、この方法の欠点は、妥協した信頼された第三者が現在、マシン上のすべてのプログラムが信頼するどんなドメインのためにでも証明書に署名することができたということです.これは長寿命サーバの重要なセキュリティリスクですが、「サイトワイド」が1つのエンドポイントに接続しているプログラムを実行するDockerコンテナを超えて拡張されない場合には、それは許容できます.
次の手順はUbuntuまたはDebian用ですその他のディストリビューションでは、必要な調整を行います.
ディレクトリを見る/usr/share/ca-certificates ディレクトリが表示されますmozilla , その中に多くの証明書ファイルがあります.たとえば、同じネストしたレベルで独自のサブディレクトリを作成します./usr/share/ca-certficates/custom そして、それを拡張して別々のファイルとして保存されたPEM形式の利子の自己署名証明書に入れてください.crt . 次に、編集/var/ca-certificates.conf そして、mozilla 証明書.例えば、
...
mozilla/USERTrust_RSA_Certification_Authority.crt
custom/example-com-self-signed.crt
custom/another-example-com-self-signed.crt
次は走るupdate-ca-certificates コマンド.完了したら、証明書へのシンボリックリンクは/etc/ssl/certs ディレクトリ.この時点でcurl ツールは、自己署名証明書をexample.com .
しかし、先に述べた指紋法では、ドメイン名ミスマッチがあっても動作しているという利点があった.IPアドレスによってターゲットHTTPSサーバを照会した場合、ミスマッチが起こります.https://1.2.3.4/a/b/ ). これがあなたの状況であるならば、あなたはエントリーを加えることができます/etc/hosts 自己署名証明書の中に記載されている正確なドメイン名を使用してWebサーバーを照会するファイル.
サイドワイドメソッドは、libopenssl ライブラリを含むcurl . しかし、Pythonのrequests ライブラリの証明書の独自のチェックの一部です.

メソッドChorn 3 :ストリップSSL
自己署名された証明書によって署名されたHTTPSウェブサイトにアクセスするためのさまざまなツールを許容する別の方法は、指紋を使用して自己署名証明書の正当性を検証した後、SSLをストリップする信頼できるプロキシサーバーを介してアクセスすることです.このようなプロキシサーバをPythonで実装することができます.また、ユーティリティプログラムを使うこともできましたstunnel それは「ユニバーサルSSLトンネル」の略です
まず、準備するconnection.conf このような設定ファイル
pid = /var/run/stunnel1.pid
CApath = /etc/ssl/certs
foreground=yes

[connection1]
verifyChain=no
verifyPeer=yes
client=yes
accept=8081
connect=1.2.3.4:443
sni=example.com
その後、実行stunnel 設定ファイルを引数にhttps://example.com としてhttp://localhost:8081 ,
$ stunnel connection.conf >& output.log &
$ curl 'http://localhost:8081/a/b/c'
例設定ファイルに注目する重要なことはverifyChain and verifyPeer オプション.彼らは指紋だけで証明書を確かめるために結合して、不完全な署名鎖を無視します.これらのオプションはstunnel 2016年7月、バージョン5.34で.ドメイン名が問題でないことに注意するもう一つのこと.The sni パラメータは、仮想サーバーが興味のある仮想ホストに指示するためだけに使用されますが、証明書の検証には何の役割もありません.
走るstunnel サイト全体が次の設定変更を行います/etc/stunnel/stunnel.conf , 削除するforeground=yes ビットセットpid to /var/run/stunnel.pid 必要に応じて追加の接続セクションを追加します.

概要
我々はセキュリティを損なうことなく自己署名証明書で動作する3つの方法を実証しました.スマートでは、我々は駐車場システムのベンダーによってデータを保護するために信頼され、我々はそのような技術を使用して信頼を正当化する.
スマートについて学ぶためにwww.smarking.com .