Dapatkan sidik jari kunci server SSH

83

Apakah ada cara untuk mendapatkan sidik jari kunci server SSH secara terprogram tanpa mengautentikasi itu?

Saya mencoba ssh -v user@host false 2>&1 | grep "Server host key", tetapi ini hang menunggu kata sandi jika kunci berbasis auth tidak diatur.

goncalopp
sumber

Jawaban:

71

Anda dapat melakukan ini dengan menggabungkan ssh-keyscandan ssh-keygen:

$ file=$(mktemp)
$ ssh-keyscan host > $file 2> /dev/null
$ ssh-keygen -l -f $file
521 de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef host (ECDSA)
4096 8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d host (RSA)
$ rm $file

(sayangnya yang lebih sederhana ssh-keyscan host | ssh-keygen -l -f /dev/stdintidak berfungsi)

Andreas Wiese
sumber
1
Mungkin begitu ssh-keygen -l -f - <(ssh-keyscan host)?
CVn
21
OpenSSH> = 7.2 ssh-keyscan dapat membaca dari stdin:ssh-keyscan host | ssh-keygen -lf -
mykhal
1
Lakukan saja:ssh-keygen -l -f <(ssh-keyscan host)
Christopher
1
Itu ekspresi yang agak buruk untuk skrip shell, karena tergantung pada shell yang mendukungnya, yang shell POSIX tidak.
Andreas Wiese
2
ssh-keygen -l -f -bekerja seperti yang diharapkan pada ssh-keygen 7.2 dan di atasnya. Ini menghasilkan beberapa baris komentar untuk STDERR yang dapat disaring, seperti yang disebutkan dalam jawaban oleh Anthony Geoghegan ataussh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Cedric Knight
56

Saya baru-baru ini harus melakukan ini sendiri jadi saya pikir saya akan menambahkan jawaban yang menunjukkan bagaimana hal ini dapat dilakukan (dengan versi OpenSSH 7.2 atau lebih baru ) dalam satu baris menggunakan proses substitusi:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Teks berikut ini menjelaskan cara kerja perintah ini dan menyoroti beberapa perbedaan perilaku antara versi OpenSSH yang lebih lama dan yang lebih baru.

Ambil kunci host publik

The ssh-keyscanperintah dikembangkan sehingga pengguna dapat memperoleh kunci publik tuan rumah tanpa perlu otentikasi ke server SSH. Dari halaman manualnya:

ssh-keyscanadalah utilitas untuk mengumpulkan kunci host ssh publik dari sejumlah host. Itu dirancang untuk membantu dalam membangun dan memverifikasi ssh_known_hostsfile.

Jenis kunci

Jenis kunci yang akan diambil ditentukan menggunakan -topsi.

  • rsa1 (Protokol SSH versi usang 1)
  • rsa
  • dsa
  • ecdsa (versi terbaru dari OpenSSH)
  • ed25519 (versi terbaru dari OpenSSH)

Dalam rilis OpenSSH modern, tipe kunci default yang akan diambil adalah rsa (sejak versi 5.1), ecdsa(sejak versi 6.0), dan ed25519(sejak versi 6.7).

Dengan versi dari ssh-keyscan(sebelum OpenSSH versi 5.1), yang standar jenis kunci adalah keluar-tanggal rsa1(SSH Protokol 1) sehingga jenis kunci akan perlu secara eksplisit ditentukan:

ssh-keyscan -t rsa,dsa hostname

Dapatkan hash sidik jari dari tombol Base64

ssh-keyscanmencetak kunci host dari server SSH dalam format yang disandikan Base64 . Untuk mengonversi ini menjadi hash sidik jari, ssh-keygenutilitas dapat digunakan dengan -lopsi untuk mencetak sidik jari dari kunci publik yang ditentukan.

Jika menggunakan Bash, Zsh (atau Korn shell), substitusi proses dapat digunakan untuk satu-liner yang praktis:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Catatan : Dengan versi OpenSSH sebelum 7.2, fungsi yang digunakan ssh-keygenuntuk membaca file, tidak menangani pipa bernama (FIFOs) dengan sangat baik sehingga metode ini tidak akan berfungsi, sehingga membutuhkan penggunaan file sementara.

Algoritma Hashing

Versi terbaru dari ssh-keygencetakan hash sidik jari SHA256 . Untuk mendapatkan hash MD5 dari sidik jari kunci server (perilaku lama), -E opsi dapat digunakan untuk menentukan algoritma hash:

ssh-keygen -E md5 -lf <(ssh-keyscan hostname 2>/dev/null)

Menggunakan pipa

Jika menggunakan shell POSIX (seperti dash) yang tidak menampilkan subtitusi proses, solusi lain menggunakan file sementara akan berfungsi. Namun, dengan versi OpenSSH yang lebih baru (sejak 7.2), sebuah pipa sederhana dapat digunakan karena ssh-keygenakan menerima -sebagai nama file untuk aliran input standar, yang memungkinkan perintah pipa satu baris.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -
Anthony G - keadilan untuk Monica
sumber
Jawaban yang bagus dan menyeluruh, ini tentu lebih baik daripada memiliki file sementara! Bolehkah saya menyarankan Anda memberikan TL; DR pada awalnya dengan versi proses substitusi, untuk membuat orang yang tidak sabar menemukannya lebih cepat? :)
goncalopp
3
Tampaknya tidak berfungsi di Ubuntu 14.04 LTS; Saya mendapatkan kesalahan "/ dev / fd / 63 bukan file kunci publik". Subproses berhasil.
Melle
@ Melleb Saya menemukan hal yang sama pada sistem 12,04 yang saya dapat akses. Saya menduga bahwa ssh-keygendari versi OpenSSH yang lama memiliki masalah dalam membaca dari pipa FIFO / bernama. Saya akan melihat ini (dan memperbarui jawaban saya) ketika saya mendapatkan waktu luang.
Anthony G - keadilan untuk Monica
3
@Melleb Setelah menghabiskan waktu luch saya mengunduh berbagai rilis kode sumber dan memasukkan printfpernyataan debugging dalam do_fingerprint()fungsi, saya menemukan bahwa dengan versi OpenSSH sebelum 7.2, fungsi yang digunakan ssh-keygenuntuk membaca file, tidak menangani pipa bernama (FIFOs) dengan sangat baik sehingga metode substitusi proses tidak akan berfungsi.
Anthony G - keadilan untuk Monica
Ini berfungsi, tetapi jika menggunakannya untuk memverifikasi sidik jari, pengguna harus menyadari bahwa ada kondisi ras: sidik jari yang Anda periksa dengan perintah ini tidak harus dari kunci yang Anda ambil, kecuali jika Anda membuang kunci sebelum memanggil ssh- keygen di atasnya.
CodeGnome
20

nmapmenyediakan kemampuan ini dengan menggunakan ssh-hostkeyskrip.

Untuk mengembalikan sidik jari heksadesimal kunci:

$ nmap [SERVER] --script ssh-hostkey

Untuk mengembalikan konten kunci:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=full

Untuk mengembalikan gelembung visual kunci

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey='visual bubble'

Untuk mengembalikan semua hal di atas:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=all

Sumber: nmap docs

Sungai kecil
sumber
3
Apakah contoh-contoh ini mengasumsikan bahwa SSH selalu berjalan pada port 22? Bagaimana jika ssh mendengarkan pada port non-standar?
Martin Vegter
3
@ MartinVegter (memparafrasekan Guarin42, yang tidak bisa berkomentar :) nmap memiliki -popsi yang dapat menentukan port, mis -p 22000. Dimungkinkan juga untuk menggunakan -vvopsi untuk meningkatkan verbositas (jumlah informasi yang diberikan)
goncalopp
2

filezilla menampilkan kunci hash dengan md5 dalam format heksadesimal .

untuk menemukan ini di mesin linux ubuntu Anda gunakan perintah ini:

ssh-keygen -l -E md5 -f <(ssh-keyscan localhost 2>/dev/null)

Catatan: ganti "localhost" dengan ip mesin yang ingin Anda periksa.

Cameron
sumber
1

Berikut ini adalah skrip shell (terutama shell Bourne tetapi menggunakan localkata kunci, yang tersedia di sebagian besar modern /bin/sh) saya sudah menulis untuk melakukan ini. Gunakan seperti ssh-hostkey hostname. Ini akan menunjukkan sidik jari format sha256 dan md5 untuk semua hostkeys untuk nama host atau alamat IP yang diberikan. Anda juga dapat secara manual menentukan " md5" atau " sha256" sebagai argumen kedua untuk hanya menampilkan format tertentu.

Ia menggunakan file temporer bukannya perpipaan untuk membuatnya kompatibel dengan paket OpenSSH yang lebih lama (seperti yang dijelaskan dalam jawaban lain). File sementara menggunakan /dev/shm(memori bersama) jika tersedia.

#!/bin/sh
usage () {
  printf '%s\n' "Usage: ssh-hostkey HOSTNAME [FPRINTHASH]"
}

ssh_hostkey () {
  local host="$1"
  local fprinthash="$2"
  local tmp=

  case "$host" in
    -h|--help|'')
      usage >&2
      return 1
      ;;
  esac

  case "$fprinthash" in
    md5|sha256|'') true;;
    *)
      usage >&2
      printf '%s\n' "Fingerprint hash may be 'md5' or 'sha256'" >&2
      return 2
      ;;
  esac

  if test -d /dev/shm
  then tmp="$(mktemp -d -p /dev/shm)"
  else tmp="$(mktemp -d)"
  fi

  trap 'trap - INT TERM EXIT; rm -rf "$tmp"' INT TERM EXIT
  ssh-keyscan "$host" > "$tmp/f" 2> /dev/null
  case "$fprinthash" in
    sha256|'') ssh-keygen -l -f "$tmp/f" 2> /dev/null;;
  esac
  case "$fprinthash" in
    md5|'') ssh-keygen -l -E md5 -f "$tmp/f" 2> /dev/null;;
  esac

  trap - INT TERM EXIT
  rm -rf "$tmp" > /dev/null 2>&1
}

ssh_hostkey "$@"
ejm
sumber