Bangun Pemindai Kerentanan Jaringan Menggunakan GO – Poin Situs

 – Beragampengetahuan
3 mins read

Bangun Pemindai Kerentanan Jaringan Menggunakan GO – Poin Situs – Beragampengetahuan

Pengujian penetrasi memungkinkan organisasi untuk menargetkan kelemahan keamanan potensial dalam jaringan dan perlu mengatasi kerentanan sebelum kompromi aktor jahat.

Dalam artikel ini, kami akan menggunakan Go untuk membuat pemindai kerentanan jaringan yang sederhana dan masuk akal, bahasa yang sempurna untuk pemrograman jaringan karena dirancang untuk diingat dan memiliki perpustakaan standar yang sangat baik.

Contents

1. Siapkan proyek kami

Buat pemindai kerentanan

Kami ingin membangun alat CLI sederhana yang akan dapat memindai jaringan host, menemukan port terbuka, menjalankan layanan dan menemukan kemungkinan kerentanan. Pemindai dimulai dengan sangat mudah, tetapi saat kami melapisi fungsi, pemindai menjadi semakin mampu.

Jadi pertama -tama, kami akan membuat proyek GO baru:

mkdir goscan
cd goscan
go mod init github.com/yourusername/goscan

Ini menginisialisasi modul GO baru untuk proyek kami, yang akan membantu kami mengelola dependensi.

Konfigurasikan paket dan lingkungan

Untuk pemindai kami, kami akan memanfaatkan beberapa kit:

package main

import (
    "fmt"
    "net"
    "os"
    "strconv"
    "sync"
    "time"
)

func main() 
    fmt.Println("GoScan - Network Vulnerability Scanner")

Ini hanya pengaturan awal kami. Untuk beberapa fitur awal, ini sudah cukup, tetapi kami akan menambahkan lebih banyak impor sesuai permintaan. Sekarang paket perpustakaan standar lainnya (seperti NET) akan memperhatikan menyelesaikan sebagian besar jaringan yang kita butuhkan, dan sinkronisasi akan melakukan konkurensi, dll.

Pertimbangan etis dan risiko pemindaian melalui jaringan

Sekarang, sebelum kita masuk ke implementasi, kita harus berbicara tentang beberapa pertimbangan moral tentang pemindaian jaringan. Di banyak bagian dunia, pemindaian atau pencacahan jaringan yang tidak sah adalah ilegal dan dianggap sebagai vektor serangan dunia maya. Anda harus selalu mengikuti aturan berikut:

  1. mengizinkan: Hanya memindai jaringan dan sistem yang Anda miliki atau memiliki izin pemindaian yang jelas.
  2. cakupan: Tentukan ruang lingkup yang jelas untuk pemindaian Anda dan jangan melebihi itu.
  3. waktu: Jangan melakukan pemindaian super untuk mengurangi layanan atau meningkatkan peringatan keamanan.
  4. Penyingkapan: Jika kerentanan ditemukan, laporkan itu bertanggung jawab dengan melaporkan kepada pemilik sistem yang sesuai.
  5. Kepatuhan hukum: Memahami dan mematuhi hukum setempat tentang pemindaian jaringan.

Penyalahgunaan alat pemindaian dapat menyebabkan tindakan hukum, kerusakan sistem, atau penolakan layanan yang tidak disengaja. Pemindai kami akan mencakup perlindungan seperti membatasi tingkat, tetapi pada akhirnya tanggung jawab terletak pada penggunaan etis pengguna itu.

2. Pemindai Port Sederhana

Penilaian kerentanan didasarkan pada pemindaian pelabuhan. Layanan yang berpotensi rentan yang disediakan oleh masing -masing port terbuka ini adalah informasi yang kami cari. Sekarang, mari kita tulis pemindai port sederhana di Go.

Implementasi pemindaian pelabuhan tingkat rendah

Pemindaian Port: Cobalah untuk membuat koneksi ke setiap port yang memungkinkan pada host target. Jika koneksi berhasil, port terbuka; Jika gagal, port akan ditutup atau disaring. Untuk fitur ini, Paket Net GO membuat kami dibahas.

Jadi, inilah versi pemindai port sederhana kami:

package main

import (
    "fmt"
    "net"
    "time"
)

func scanPort(host string, port int, timeout time.Duration) bool 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    
    if err != nil 
        return false
    
    
    conn.Close()
    return true


func main() 
    host := "localhost" 
    timeout := time.Second * 2
    
    fmt.Printf("Scanning host: %s\n", host)
    
    
    for port := 1; port <= 1024; port++ 
        if scanPort(host, port, timeout) 
            fmt.Printf("Port %d is open\n", port)
        
    
    
    fmt.Println("Scan complete")

Menggunakan paket jaringan

Kode di atas menggunakan Paket Perangkat Lunak GO NET, yang menyediakan antarmuka dan fungsi I/O jaringan. Jadi, apa pekerjaan utamanya?

  1. net.dialtimeout: Fungsi ini mencoba untuk terhubung ke alamat jaringan TCP melalui batas waktu. Ini mengembalikan koneksi dan mengembalikan kesalahan (jika ada).
  2. Pemrosesan koneksi: Jika terhubung tanpa masalah, kami tahu itu terbuka, kami segera menutup koneksi untuk membuka sumber daya.
  3. Parameter batas waktu: Kami menentukan jeda untuk menghindari tergantung pada port penyaringan terbuka apa pun. Dua detik adalah nilai awal yang baik, tetapi dapat disesuaikan sesuai dengan kondisi jaringan.

Uji pemindaian pertama kami

Sekarang mari kita lakukan pemindai sederhana di localhost kami, di mana kami mungkin menjalankan beberapa layanan.

  1. Simpan kode ke file bernama main.go
  2. Jalankan go run main.go

Ini akan menunjukkan port lokal mana yang terbuka. Pada mesin pengembangan normal, Anda mungkin memiliki 80 (http), 443 (http), atau sejumlah port basis data tergantung pada layanan yang Anda miliki.

Anda mungkin mendapatkan beberapa output sampel:

Scanning host: localhost
Port 22 is open
Port 80 is open
Port 443 is open
Scan complete

Menggunakan pemindai dasar ini bekerja, tetapi membawa beberapa kelemahan besar:

  1. kecepatan: Nyeri lambat karena akan memindai port secara berurutan.
  2. informasi: Beri tahu kami apakah port terbuka dan tidak ada informasi layanan.
  3. Kisaran terbatas: Kita hanya perlu memindai 1024 port pertama.

Keterbatasan ini membuat pemindai kami tidak praktis untuk digunakan di dunia nyata.

3. Perbaikan dari sini: Pemindaian multithreaded

Mengapa versi pertama lambat

Pemindai pelabuhan pertama kami bekerja, meskipun lambat tersedia. Masalahnya adalah metode berurutan – menyelidiki satu port pada satu waktu. Ketika host memiliki banyak port tertutup/disaring, kami membuang waktu menunggu untuk terhubung ke setiap port sebelum pindah ke port lain.

Untuk menunjukkan masalahnya, mari kita lihat waktu pemindai dasar kami:

  • Skenario terburuk pemindaian port 1024 pertama akan memakan waktu hingga 2048 detik (lebih dari 34 menit) dan menggunakan 2 detik
  • Namun, bahkan jika koneksi ke port shutdown gagal segera, metode ini kurang efisien karena latensi jaringan.

Pendekatan tunggal ini adalah hambatan untuk alat pemindaian kerentanan nyata.

Tambahkan dukungan utas

GO sangat pandai menggunakan goroutine dan saluran untuk konkurensi. Oleh karena itu, kami menggunakan fitur -fitur ini untuk mencoba memindai beberapa port sekaligus, yang sangat meningkatkan kinerja.

Sekarang, mari kita buat pemindai port multithreaded:

package main

import (
    "fmt"
    "net"
    "sync"
    "time"
)

type Result struct 
    Port  int
    State bool


func scanPort(host string, port int, timeout time.Duration) Result 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    
    if err != nil 
        return ResultPort: port, State: false
    
    
    conn.Close()
    return ResultPort: port, State: true


func scanPorts(host string, start, end int, timeout time.Duration) []Result 
    var results []Result
    var wg sync.WaitGroup
    
    
    resultChan := make(chan Result, end-start+1)
    
    
    
    semaphore := make(chan struct, 100) 
    
    
    for port := start; port <= end; port++ 
        wg.Add(1)
        go func(p int) 
            defer wg.Done()
            
            
            semaphore <- struct
            defer func()  <-semaphore () 
            
            result := scanPort(host, p, timeout)
            resultChan <- result
        (port)
    
    
    
    go func() 
        wg.Wait()
        close(resultChan)
    ()
    
    
    for result := range resultChan 
        if result.State 
            results = append(results, result)
        
    
    
    return results


func main() 
    host := "localhost" 
    startPort := 1
    endPort := 1024
    timeout := time.Millisecond * 500 
    
    fmt.Printf("Scanning %s from port %d to %d\n", host, startPort, endPort)
    startTime := time.Now()
    
    results := scanPorts(host, startPort, endPort, timeout)
    
    elapsed := time.Since(startTime)
    
    fmt.Printf("\nScan completed in %s\n", elapsed)
    fmt.Printf("Found %d open ports:\n", len(results))
    
    for _, result := range results 
        fmt.Printf("Port %d is open\n", result.Port)
    

Hasil dari beberapa utas

Sekarang mari kita lihat pertumbuhan kinerja yang kami tambahkan di pemindai yang lebih baik dan mekanisme konkurensi:

  1. Goroutine: Untuk meningkatkan efisiensi pemindaian, kami memulai goroutine untuk setiap port yang perlu dipindai, jadi ketika kami memeriksa satu port, kami dapat memeriksa port lain secara bersamaan.
  2. Waitgroup:sinkronis. Tim yang menunggu, kami mendorong Golotis, kami ingin menunggu penyelesaian mereka. WaitGroup membantu kami melacak semua goroutine yang berjalan dan menunggu mereka menyelesaikannya.
  3. Saluran Hasil: Kami membuat saluran buffer agar hasil dari semua goroutine.
  4. Mode semaphore: Gunakan semaphores, diimplementasikan menggunakan saluran untuk membatasi jumlah pemindaian yang diizinkan secara paralel. Inilah yang mencegah kita untuk membanjiri sistem target yang sebenarnya dan bahkan tidak dapat membuka banyak mesin yang terhubung.
  5. Kurangi batas waktu: Karena kami melakukan banyak pemindaian ini secara paralel, kami menggunakan batas waktu yang lebih rendah.

Kesenjangan kinerja sangat besar. Jadi ketika kami menerapkan fungsi ini, memungkinkan kami untuk memindai 1024 port dalam beberapa menit, yang tentu saja kurang dari setengah jam.

Output sampel:

Scanning localhost from port 1 to 1024
Scan completed in 3.2s
Found 3 open ports:
Port 22 is open
Port 80 is open
Port 443 is open

Pendekatan multithreaded baik untuk rentang port yang lebih besar dan beberapa host. Pola semaphore memastikan bahwa meskipun memindai lebih dari seribu port, kami tidak kehabisan sumber daya sistem.

4. Tambahkan Deteksi Layanan

Sekarang kami memiliki pemindai port yang cepat dan efisien, langkah selanjutnya adalah mengetahui layanan yang berjalan di port terbuka ini. Ini sering disebut “sidik jari layanan” atau “crawl spanduk”, yang merupakan proses ketika kami terhubung ke port terbuka dan memeriksa data pengembalian.

Menerapkan Banner Grab

Banner Crawl adalah saat kami membuka layanan dan membaca respons (Banner) itu membawa kami. Jadi ini cara yang bagus untuk menentukan apakah sesuatu berhasil, karena banyak layanan diidentifikasi dalam spanduk ini.

Sekarang mari kita ambil spanduk ke pemindai kami:

package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
    "sync"
    "time"
)

type ScanResult struct 
    Port     int
    State    bool
    Service  string
    Banner   string
    Version  string


func grabBanner(host string, port int, timeout time.Duration) (string, error) 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    if err != nil 
        return "", err
    
    defer conn.Close()
    
    conn.SetReadDeadline(time.Now().Add(timeout))
    
    
    
    if port == 80 

func identifyService(port int, banner string) (string, string)  strings.Contains(lowerBanner, "apache") 

func scanPort(host string, port int, timeout time.Duration) ScanResult 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    
    if err != nil 
        return ScanResultPort: port, State: false
    
    
    conn.Close()
    
    banner, err := grabBanner(host, port, timeout)
    
    service := "Unknown"
    version := "Unknown"
    
    if err == nil && banner != "" 
        service, version = identifyService(port, banner)
    
    
    return ScanResult
        Port:    port,
        State:   true,
        Service: service,
        Banner:  banner,
        Version: version,
    


func scanPorts(host string, start, end int, timeout time.Duration) []ScanResult 
    var results []ScanResult
    var wg sync.WaitGroup
    
    resultChan := make(chan ScanResult, end-start+1)
    
    semaphore := make(chan struct, 100)
    
    for port := start; port <= end; port++ 
        wg.Add(1)
        go func(p int) 
            defer wg.Done()
            
            semaphore <- struct
            defer func()  <-semaphore ()
            
            result := scanPort(host, p, timeout)
            resultChan <- result
        (port)
    
    
    go func() 
        wg.Wait()
        close(resultChan)
    ()
    
    for result := range resultChan 
        if result.State 
            results = append(results, result)
        
    
    
    return results


func main() 
    host := "localhost"
    startPort := 1
    endPort := 1024
    timeout := time.Millisecond * 800 
    
    fmt.Printf("Scanning %s from port %d to %d\n", host, startPort, endPort)
    startTime := time.Now()
    
    results := scanPorts(host, startPort, endPort, timeout)
    
    elapsed := time.Since(startTime)
    
    fmt.Printf("\nScan completed in %s\n", elapsed)
    fmt.Printf("Found %d open ports:\n\n", len(results))
    
    fmt.Println("PORT\tSERVICE\tVERSION\tBANNER")
    fmt.Println("----\t-------\t-------\t------")
    for _, result := range results 
        bannerPreview := ""
        if len(result.Banner) > 30 
            bannerPreview = result.Banner[:30] + "..."
         else 
            bannerPreview = result.Banner
        
        
        fmt.Printf("%d\t%s\t%s\t%s\n", 
            result.Port, 
            result.Service, 
            result.Version, 
            bannerPreview)
    

Identifikasi layanan berjalan

Kami menggunakan dua strategi utama untuk deteksi layanan:

  1. Identifikasi Berbasis Port: Dengan memetakan nomor port umum (misalnya, port 80 adalah http), kita dapat menebak layanan.
  2. Analisis spanduk: Kami menggunakan teks spanduk dan mencari pengidentifikasi layanan dan informasi versi.

Fitur pertama Grabbanner mencoba mendapatkan respons pertama dari layanan. Beberapa layanan seperti HTTP mengharuskan kami mengirim permintaan dan menerima balasan, dan kami menggunakan kasus di mana kami menambahkan kasus tertentu.

Deteksi Versi Dasar

Deteksi versi penting untuk mengidentifikasi kerentanan. Jika memungkinkan, pemindai kami mem -parsing spanduk layanan untuk informasi versi:

  1. Ssh: Informasi versi biasanya disediakan dalam bentuk “ssh-2.0-openssh_7.4”.
  2. Server http: Informasi versinya biasanya digunakan dalam judul respons untuk merespons, seperti “Server: Apache/2.4.29”
  3. Server database: Informasi versi dapat diungkapkan dalam pesan selamat datang

Sekarang, output mengembalikan informasi lebih lanjut untuk setiap port terbuka:

Scanning localhost from port 1 to 1024
Scan completed in 5.4s
Found 3 open ports:

PORT    SERVICE VERSION BANNER
----    ------- ------- ------
22      SSH     2.0     SSH-2.0-OpenSSH_8.4p1 Ubuntu-6
80      HTTP    Apache/2.4.41 Server: Apache/2.4.41 (Ubuntu)
443     HTTPS   Unknown Connection closed by foreign...

Informasi yang ditingkatkan ini lebih berharga untuk penilaian kerentanan.

5. Implementasi Deteksi Kerentanan

Sekarang kami dapat menyebutkan layanan yang berjalan dan versi apa mereka, dan kami akan menerapkan deteksi kerentanan. Informasi layanan akan dianalisis dan dibandingkan dengan kerentanan yang diketahui.

Tulis tes kerentanan sederhana

Kami akan membentuk database dari kerentanan yang diketahui berdasarkan layanan umum dan versi. Untuk kesederhanaan, kami akan membuat database kerentanan internal, meskipun pada kenyataannya, pemindai kemungkinan besar akan meminta database kerentanan eksternal (seperti CVE atau NVD).

Sekarang, mari kita perluas kode untuk mendeteksi kerentanan:

package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
    "sync"
    "time"
)

type ScanResult struct 
    Port          int
    State         bool
    Service       string
    Banner        string
    Version       string
    Vulnerabilities []Vulnerability


type Vulnerability struct 
    ID          string
    Description string
    Severity    string
    Reference   string


var vulnerabilityDB = []struct 
    Service     string
    Version     string
    Vulnerability Vulnerability

    
        Service: "SSH",
        Version: "OpenSSH_7.4",
        Vulnerability: Vulnerability
            ID:          "CVE-2017-15906",
            Description: "The process_open function in sftp-server.c in OpenSSH before 7.6 does not properly prevent write operations in read-only mode",
            Severity:    "Medium",
            Reference:   "",
        ,
    ,
    
        Service: "HTTP",
        Version: "Apache/2.4.29",
        Vulnerability: Vulnerability
            ID:          "CVE-2019-0211",
            Description: "Apache HTTP Server 2.4.17 to 2.4.38 - Local privilege escalation through mod_prefork and mod_http2",
            Severity:    "High",
            Reference:   "https://nvd.nist.gov/vuln/detail/CVE-2019-0211",
        ,
    ,
    
        Service: "HTTP",
        Version: "Apache/2.4.41",
        Vulnerability: Vulnerability
            ID:          "CVE-2020-9490",
            Description: "A specially crafted value for the 'Cache-Digest' header can cause a heap overflow in Apache HTTP Server 2.4.0-2.4.41",
            Severity:    "High",
            Reference:   "",
        ,
    ,
    
        Service: "MySQL",
        Version: "5.7",
        Vulnerability: Vulnerability
            ID:          "CVE-2020-2922",
            Description: "Vulnerability in MySQL Server allows unauthorized users to obtain sensitive information",
            Severity:    "Medium",
            Reference:   "https://nvd.nist.gov/vuln/detail/CVE-2020-2922",
        ,
    ,
    



func checkVulnerabilities(service, version string) []Vulnerability 
    var vulnerabilities []Vulnerability
    
    for _, vuln := range vulnerabilityDB 
        
        if vuln.Service == service && strings.Contains(version, vuln.Version) 
            vulnerabilities = append(vulnerabilities, vuln.Vulnerability)
        
    
    
    return vulnerabilities



func grabBanner(host string, port int, timeout time.Duration) (string, error)  port == 8080 

func identifyService(port int, banner string) (string, string)  
       strings.Contains(lowerBanner, "nginx") 
        if port == 443 
            service = "HTTPS"
         else 
            service = "HTTP"
        
        
        if strings.Contains(banner, "Server:") 
            parts := strings.Split(banner, "Server:")
            if len(parts) >= 2 
                version = strings.TrimSpace(parts[1])
            
        
    
    
    return service, version


func scanPort(host string, port int, timeout time.Duration) ScanResult 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    
    if err != nil 
        return ScanResultPort: port, State: false
    
    
    conn.Close()
    
    banner, err := grabBanner(host, port, timeout)
    
    service := "Unknown"
    version := "Unknown"
    
    if err == nil && banner != "" 
        service, version = identifyService(port, banner)
    
    
    vulnerabilities := checkVulnerabilities(service, version)
    
    return ScanResult
        Port:           port,
        State:          true,
        Service:        service,
        Banner:         banner,
        Version:        version,
        Vulnerabilities: vulnerabilities,
    


func scanPorts(host string, start, end int, timeout time.Duration) []ScanResult 
    var results []ScanResult
    var wg sync.WaitGroup
    
    resultChan := make(chan ScanResult, end-start+1)
    
    semaphore := make(chan struct, 100)
    
    for port := start; port <= end; port++ 
        wg.Add(1)
        go func(p int) 
            defer wg.Done()
            
            semaphore <- struct
            defer func()  <-semaphore ()
            
            result := scanPort(host, p, timeout)
            resultChan <- result
        (port)
    
    
    go func() 
        wg.Wait()
        close(resultChan)
    ()
    
    for result := range resultChan 
        if result.State 
            results = append(results, result)
        
    
    
    return results


func main() 
    host := "localhost"
    startPort := 1
    endPort := 1024
    timeout := time.Second * 1 
    
    fmt.Printf("Scanning %s from port %d to %d\n", host, startPort, endPort)
    startTime := time.Now()
    
    results := scanPorts(host, startPort, endPort, timeout)
    
    elapsed := time.Since(startTime)
    
    fmt.Printf("\nScan completed in %s\n", elapsed)
    fmt.Printf("Found %d open ports:\n\n", len(results))
    
    fmt.Println("PORT\tSERVICE\tVERSION")
    fmt.Println("----\t-------\t-------")
    for _, result := range results 
        fmt.Printf("%d\t%s\t%s\n", 
            result.Port, 
            result.Service, 
            result.Version)
        
        if len(result.Vulnerabilities) > 0 
            fmt.Println("  Vulnerabilities:")
            for _, vuln := range result.Vulnerabilities 
                fmt.Printf("    [%s] %s - %s\n", 
                    vuln.Severity, 
                    vuln.ID, 
                    vuln.Description)
                fmt.Printf("    Reference: %s\n\n", vuln.Reference)
            
        
    
package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
    "sync"
    "time"
)

type ScanResult struct 
    Port          int
    State         bool
    Service       string
    Banner        string
    Version       string
    Vulnerabilities []Vulnerability


type Vulnerability struct 
    ID          string
    Description string
    Severity    string
    Reference   string


var vulnerabilityDB = []struct 
    Service     string
    Version     string
    Vulnerability Vulnerability

    
        Service: "SSH",
        Version: "OpenSSH_7.4",
        Vulnerability: Vulnerability
            ID:          "CVE-2017-15906",
            Description: "The process_open function in sftp-server.c in OpenSSH before 7.6 does not properly prevent write operations in read-only mode",
            Severity:    "Medium",
            Reference:   "",
        ,
    ,
    
        Service: "HTTP",
        Version: "Apache/2.4.29",
        Vulnerability: Vulnerability
            ID:          "CVE-2019-0211",
            Description: "Apache HTTP Server 2.4.17 to 2.4.38 - Local privilege escalation through mod_prefork and mod_http2",
            Severity:    "High",
            Reference:   "https://nvd.nist.gov/vuln/detail/CVE-2019-0211",
        ,
    ,
    
        Service: "HTTP",
        Version: "Apache/2.4.41",
        Vulnerability: Vulnerability
            ID:          "CVE-2020-9490",
            Description: "A specially crafted value for the 'Cache-Digest' header can cause a heap overflow in Apache HTTP Server 2.4.0-2.4.41",
            Severity:    "High",
            Reference:   "",
        ,
    ,
    
        Service: "MySQL",
        Version: "5.7",
        Vulnerability: Vulnerability
            ID:          "CVE-2020-2922",
            Description: "Vulnerability in MySQL Server allows unauthorized users to obtain sensitive information",
            Severity:    "Medium",
            Reference:   "https://nvd.nist.gov/vuln/detail/CVE-2020-2922",
        ,
    ,
    



func checkVulnerabilities(service, version string) []Vulnerability 
    var vulnerabilities []Vulnerability
    
    for _, vuln := range vulnerabilityDB 
        
        if vuln.Service == service && strings.Contains(version, vuln.Version) 
            vulnerabilities = append(vulnerabilities, vuln.Vulnerability)
        
    
    
    return vulnerabilities



func grabBanner(host string, port int, timeout time.Duration) (string, error)  port == 8080 

func identifyService(port int, banner string) (string, string)  
       strings.Contains(lowerBanner, "nginx") 
        if port == 443 
            service = "HTTPS"
         else 
            service = "HTTP"
        
        
        if strings.Contains(banner, "Server:") 
            parts := strings.Split(banner, "Server:")
            if len(parts) >= 2 
                version = strings.TrimSpace(parts[1])
            
        
    
    
    return service, version


func scanPort(host string, port int, timeout time.Duration) ScanResult 
    target := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", target, timeout)
    
    if err != nil 
        return ScanResultPort: port, State: false
    
    
    conn.Close()
    
    banner, err := grabBanner(host, port, timeout)
    
    service := "Unknown"
    version := "Unknown"
    
    if err == nil && banner != "" 
        service, version = identifyService(port, banner)
    
    
    vulnerabilities := checkVulnerabilities(service, version)
    
    return ScanResult
        Port:           port,
        State:          true,
        Service:        service,
        Banner:         banner,
        Version:        version,
        Vulnerabilities: vulnerabilities,
    


func scanPorts(host string, start, end int, timeout time.Duration) []ScanResult 
    var results []ScanResult
    var wg sync.WaitGroup
    
    resultChan := make(chan ScanResult, end-start+1)
    
    semaphore := make(chan struct, 100)
    
    for port := start; port <= end; port++ 
        wg.Add(1)
        go func(p int) 
            defer wg.Done()
            
            semaphore <- struct
            defer func()  <-semaphore ()
            
            result := scanPort(host, p, timeout)
            resultChan <- result
        (port)
    
    
    go func() 
        wg.Wait()
        close(resultChan)
    ()
    
    for result := range resultChan 
        if result.State 
            results = append(results, result)
        
    
    
    return results


func main() 
    host := "localhost"
    startPort := 1
    endPort := 1024
    timeout := time.Second * 1 
    
    fmt.Printf("Scanning %s from port %d to %d\n", host, startPort, endPort)
    startTime := time.Now()
    
    results := scanPorts(host, startPort, endPort, timeout)
    
    elapsed := time.Since(startTime)
    
    fmt.Printf("\nScan completed in %s\n", elapsed)
    fmt.Printf("Found %d open ports:\n\n", len(results))
    
    fmt.Println("PORT\tSERVICE\tVERSION")
    fmt.Println("----\t-------\t-------")
    for _, result := range results 
        fmt.Printf("%d\t%s\t%s\n", 
            result.Port, 
            result.Service, 
            result.Version)
        
        if len(result.Vulnerabilities) > 0 
            fmt.Println("  Vulnerabilities:")
            for _, vuln := range result.Vulnerabilities 
                fmt.Printf("    [%s] %s - %s\n", 
                    vuln.Severity, 
                    vuln.ID, 
                    vuln.Description)
                fmt.Printf("    Reference: %s\n\n", vuln.Reference)
            
        
    

Pencocokan kerentanan berbasis versi

Kami memiliki metode pencocokan versi naif untuk mendeteksi kerentanan:

  1. Pertandingan langsung: Di sini kami mencocokkan jenis layanan dan versi dengan database kerentanan kami.
  2. Pertandingan parsial: Untuk pencocokan versi rentan, kami melakukan pemeriksaan penahanan pada string versi, yang dapat mengidentifikasi sistem yang rentan bahkan jika string versi berisi informasi tambahan.

Dalam pemindai sungguhan, pencocokan ini akan lebih kompleks, mengingat:

  • Rentang Versi (IE Versi 2.4.0 hingga 2.4.38 terpengaruh)
  • Kerentanan spesifik konfigurasi
  • Masalah khusus OS
  • Perbandingan versi yang lebih halus

Laporkan apa yang kami temukan

Hasil pelaporan adalah langkah terakhir dalam deteksi kerentanan dan perlu diselesaikan dalam format yang ringkas dan jelas. Sekarang pemindai kami:

  1. Cantumkan semua port terbuka dengan informasi layanan dan versi
  2. Untuk setiap layanan yang rentan, tunjukkan:
    • ID kerentanan (seperti nomor CVE)
    • Deskripsi kerentanan
    • Tingkat keparahan
    • Lihat tautan untuk informasi lebih lanjut

Output sampel:

Scanning localhost from port 1 to 1024
Scan completed in 6.2s
Found 3 open ports:

PORT    SERVICE VERSION
----    ------- -------
22      SSH     OpenSSH_7.4p1
  Vulnerabilities:
    [Medium] CVE-2017-15906 - The process_open function in sftp-server.c in OpenSSH before 7.6 does not properly prevent write operations in read-only mode
    Reference: 

80      HTTP    Apache/2.4.41
  Vulnerabilities:
    [High] CVE-2020-9490 - A specially crafted value for the 'Cache-Digest' header can cause a heap overflow in Apache HTTP Server 2.4.0-2.4.41
    Reference: 

443     HTTPS   Unknown

Data kerentanan yang terperinci ini memandu para ahli keamanan siber untuk dengan cepat mengidentifikasi dan memberi peringkat masalah keamanan yang perlu ditangani.

Sentuhan dan penggunaan terakhir

Sekarang Anda memiliki pemindai kerentanan dasar dengan deteksi layanan dan pencocokan kerentanan; Sekarang, mari kita memoles sedikit untuk membuatnya lebih praktis untuk digunakan di dunia nyata.

Parameter baris perintah

Pemindai kami harus dapat dikonfigurasi melalui bendera baris perintah yang menetapkan opsi target, rentang port, dan pemindaian. Menggunakan paket logo Go sederhana.

Selanjutnya, mari tambahkan parameter baris perintah:

package main

import (
    "bufio"
    "encoding/json"
    "flag"
    "fmt"
    "net"
    "os"
    "strings"
    "sync"
    "time"
)

type ScanResult struct 
    Port            int
    State           bool
    Service         string
    Banner          string
    Version         string
    Vulnerabilities []Vulnerability


type Vulnerability struct 
    ID          string
    Description string
    Severity    string
    Reference   string


var vulnerabilityDB = []struct 
    Service       string
    Version       string
    Vulnerability Vulnerability

    



func main() 
    hostPtr := flag.String("host", "", "Target host to scan (required)")
    startPortPtr := flag.Int("start", 1, "Starting port number")
    endPortPtr := flag.Int("end", 1024, "Ending port number")
    timeoutPtr := flag.Int("timeout", 1000, "Timeout in milliseconds")
    concurrencyPtr := flag.Int("concurrency", 100, "Number of concurrent scans")
    formatPtr := flag.String("format", "text", "Output format: text, json, or csv")
    verbosePtr := flag.Bool("verbose", false, "Show verbose output including banners")
    outputFilePtr := flag.String("output", "", "Output file (default is stdout)")
    
    flag.Parse()
    
    if *hostPtr == "" 
        fmt.Println("Error: host is required")
        flag.Usage()
        os.Exit(1)
    
    
    if *startPortPtr < 1 

func outputText(w *os.File, results []ScanResult, elapsed time.Duration, verbose bool) 
    fmt.Fprintf(w, "\nScan completed in %s\n", elapsed)
    fmt.Fprintf(w, "Found %d open ports:\n\n", len(results))
    
    if len(results) == 0 
        fmt.Fprintf(w, "No open ports found.\n")
        return
    
    
    fmt.Fprintf(w, "PORT\tSERVICE\tVERSION\n")
    fmt.Fprintf(w, "----\t-------\t-------\n")
    
    for _, result := range results 
        fmt.Fprintf(w, "%d\t%s\t%s\n", 
            result.Port, 
            result.Service, 
            result.Version)
        
        if verbose 
            fmt.Fprintf(w, "  Banner: %s\n", result.Banner)
        
        
        if len(result.Vulnerabilities) > 0 
            fmt.Fprintf(w, "  Vulnerabilities:\n")
            for _, vuln := range result.Vulnerabilities 
                fmt.Fprintf(w, "    [%s] %s - %s\n", 
                    vuln.Severity, 
                    vuln.ID, 
                    vuln.Description)
                fmt.Fprintf(w, "    Reference: %s\n\n", vuln.Reference)
            
        
    


func outputJSON(w *os.File, results []ScanResult, elapsed time.Duration) 
    output := struct 
        ScanTime   string       `json:"scan_time"`
        ElapsedTime string       `json:"elapsed_time"`
        TotalPorts int          `json:"total_ports"`
        OpenPorts  int          `json:"open_ports"`
        Results    []ScanResult `json:"results"`
    
        ScanTime:    time.Now().Format(time.RFC3339),
        ElapsedTime: elapsed.String(),
        TotalPorts:  0, 
        OpenPorts:   len(results),
        Results:     results,
    
    
    encoder := json.NewEncoder(w)
    encoder.SetIndent("", "  ")
    encoder.Encode(output)


func outputCSV(w *os.File, results []ScanResult, elapsed time.Duration, verbose bool) 
    fmt.Fprintf(w, "Port,Service,Version,Vulnerability ID,Severity,Description\n")
    
    for _, result := range results 
        if len(result.Vulnerabilities) == 0 
            fmt.Fprintf(w, "%d,%s,%s,,,\n", 
                result.Port, 
                escapeCSV(result.Service), 
                escapeCSV(result.Version))
         else 
            for _, vuln := range result.Vulnerabilities 
                fmt.Fprintf(w, "%d,%s,%s,%s,%s,%s\n", 
                    result.Port, 
                    escapeCSV(result.Service), 
                    escapeCSV(result.Version),
                    escapeCSV(vuln.ID),
                    escapeCSV(vuln.Severity),
                    escapeCSV(vuln.Description))
            
        
    
    
    fmt.Fprintf(w, "\n# Scan completed in %s, found %d open ports\n", 
        elapsed, len(results))


func escapeCSV(s string) string 
    if strings.Contains(s, ",") 

Format output

Pemindai kami sekarang dapat menghasilkan tiga format:

  1. teks: Mudah dibaca, mudah ditulis, sempurna untuk penggunaan interaktif.
  2. Json: Output terstruktur dapat digunakan untuk pemrosesan mesin dan integrasi dengan alat lain.
  3. CSV: Format kompatibel spreadsheet untuk analisis dan pelaporan.

Jika detail diatur, teks output juga memberikan informasi lebih lanjut, seperti informasi spanduk mentah. Ini juga nyaman untuk debugging atau analisis mendalam.

Contoh Penggunaan dan Hasil

Jadi jika Anda menggunakan pemindai kami pada kesempatan yang berbeda, berikut adalah beberapa kemungkinan:

Pemindaian dasar dari satu host:

$ go run main.go -host example.com

Pindai rentang port spesifik:

$ go run main.go -host example.com -start 80 -end 443

Simpan hasilnya ke file JSON:

$ go run main.go -host example.com -format json -output results.json

Pemindaian waktu yang lama:

$ go run main.go -host example.com -verbose -timeout 2000

Pemindaian memiliki konkurensi yang lebih tinggi untuk hasil yang lebih cepat:

$ go run main.go -host example.com -concurrency 200

Contoh output teks:

Scanning example.com from port 1 to 1024
Scan completed in 12.6s
Found 3 open ports:

PORT    SERVICE VERSION
----    ------- -------
22      SSH     OpenSSH_7.4p1
  Vulnerabilities:
    [Medium] CVE-2017-15906 - The process_open function in sftp-server.c in OpenSSH before 7.6 does not properly prevent write operations in read-only mode
    Reference: 

80      HTTP    Apache/2.4.41
  Vulnerabilities:
    [High] CVE-2020-9490 - A specially crafted value for the 'Cache-Digest' header can cause a heap overflow in Apache HTTP Server 2.4.0-2.4.41
    Reference: 

443     HTTPS   nginx/1.18.0

Contoh Output JSON:


  "scan_time": "2025-03-18T14:30:00Z",
  "elapsed_time": "12.6s",
  "total_ports": 1024,
  "open_ports": 3,
  "results": [
    
      "Port": 22,
      "State": true,
      "Service": "SSH",
      "Banner": "SSH-2.0-OpenSSH_7.4p1",
      "Version": "OpenSSH_7.4p1",
      "Vulnerabilities": [
        
          "ID": "CVE-2017-15906",
          "Description": "The process_open function in sftp-server.c in OpenSSH before 7.6 does not properly prevent write operations in read-only mode",
          "Severity": "Medium",
          "Reference": ""
        
      ]
    ,
    
      "Port": 80,
      "State": true,
      "Service": "HTTP",
      "Banner": "HTTP/1.1 200 OK\r\nServer: Apache/2.4.41",
      "Version": "Apache/2.4.41",
      "Vulnerabilities": [
        
          "ID": "CVE-2020-9490",
          "Description": "A specially crafted value for the 'Cache-Digest' header can cause a heap overflow in Apache HTTP Server 2.4.0-2.4.41",
          "Severity": "High",
          "Reference": ""
        
      ]
    ,
    
      "Port": 443,
      "State": true,
      "Service": "HTTPS",
      "Banner": "HTTP/1.1 200 OK\r\nServer: nginx/1.18.0",
      "Version": "nginx/1.18.0",
      "Vulnerabilities": []
    
  ]

Kami telah membangun pemindai kerentanan jaringan yang kuat di Go yang menunjukkan penerapan bahasa terhadap alat keamanan. Pemindai kami dengan cepat membuka port, menentukan layanan yang berjalan di atasnya, dan menentukan apakah ada kerentanan yang diketahui.

Ini memberikan informasi yang berguna tentang layanan yang berjalan di jaringan, termasuk multithreading, sidik jari layanan, dan berbagai format output.

Ingatlah bahwa alat -alat seperti pemindai hanya dapat digunakan dalam parameter etika dan hukum dan memindai sistem target dengan otorisasi yang sesuai. Pemindaian kerentanan reguler adalah aspek kunci dari postur keselamatan yang baik ketika dilakukan secara bertanggung jawab dan dapat membantu melindungi sistem Anda dari ancaman.

Anda dapat menemukan kode sumber lengkap untuk proyek ini di GitHub

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Bangun #Pemindai #Kerentanan #Jaringan #Menggunakan #Poin #Situs

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *