Python-penetration-testing-network-scanner

提供:Dev Guides
移動先:案内検索

Pythonネットワークスキャナー

ポートスキャンは、特定のホストで使用可能な開いているポートを見つけるために使用される監視技術として定義できます。 ネットワーク管理者、ペネトレーションテスター、またはハッカーがこの手法を使用できます。 ターゲットシステムから最大の情報を取得するために、要件に従ってポートスキャナーを構成できます。

次に、ポートスキャンの実行後に取得できる情報を検討します-

  • 開いているポートに関する情報。
  • 各ポートで実行されているサービスに関する情報。
  • ターゲットホストのOSおよびMACアドレスに関する情報。

ポートスキャンは、ドアや窓をすべてチェックして、開いているものを確認することにより、家に入ることを望む泥棒のようなものです。 前述のように、インターネット上の通信に使用されるTCP/IPプロトコルスイートは、TCPとUDPの2つのプロトコルで構成されています。 両方のプロトコルには、0〜65535のポートがあります。 したがって、システムの不必要なポートを閉じることを常にお勧めします。したがって、ロックするには65000以上のドア(ポート)があります。 これらの65535ポートは、次の3つの範囲に分けることができます-

  • システムポートまたは既知のポート:0〜1023
  • ユーザーまたは登録済みポート:1024〜49151 *動的ポートまたはプライベートポート:すべて> 49151

ソケットを使用したポートスキャナー

前の章で、ソケットとは何かについて説明しました。 次に、ソケットを使用して簡単なポートスキャナーを構築します。 以下は、ソケットを使用したポートスキャナー用のPythonスクリプトです-

from socket import*
import time
startTime = time.time()

if __name__ == '__main__':
   target = input('Enter the host to be scanned: ')
   t_IP = gethostbyname(target)
   print ('Starting scan on host: ', t_IP)

   for i in range(50, 500):
      s = socket(AF_INET, SOCK_STREAM)

      conn = s.connect_ex((t_IP, i))
      if(conn == 0) :
         print ('Port %d: OPEN' % (i,))
      s.close()
print('Time taken:', time.time() - startTime)

上記のスクリプトを実行すると、ホスト名の入力が求められます。Webサイトの名前などのホスト名を指定できますが、ポートスキャンは犯罪と見なされるか、犯罪と見なされる可能性があるため注意してください。 ターゲットとするサーバーまたはコンピューターの所有者からの明示的な書面による許可なしに、WebサイトまたはIPアドレスに対してポートスキャナーを実行しないでください。 ポートスキャンは、誰かの家に行き、ドアや窓をチェックするようなものです。 そのため、localhostまたは自分のWebサイト(ある場合)でポートスキャナーを使用することをお勧めします。

出力

上記のスクリプトは、次の出力を生成します-

Enter the host to be scanned: localhost
Starting scan on host: 127.0.0.1
Port 135: OPEN
Port 445: OPEN
Time taken: 452.3990001678467

出力は、50〜500の範囲(スクリプトで提供)で、このポートスキャナーが2つのポートを検出したことを示しています-ポート135と445が開いています。 この範囲を変更して、他のポートを確認できます。

ICMPを使用したポートスキャナー(ネットワーク内のライブホスト)

ICMPはポートスキャンではありませんが、リモートホストをpingしてホストが起動しているかどうかを確認するために使用されます。 このスキャンは、ネットワーク内のライブホストの数を確認する必要がある場合に役立ちます。 ICMP ECHO要求をホストに送信し、そのホストが稼働している場合は、ICMP ECHO応答を返します。

ICMPを使用したポートスキャナー

ICMP要求を送信する上記のプロセスは、pingスキャンとも呼ばれ、オペレーティングシステムのpingコマンドによって提供されます。

Ping Sweepの概念

実際、ある意味では、pingスイープはpingスイープとも呼ばれます。 唯一の違いは、pingスイープが特定のネットワーク範囲で複数のマシンの可用性を見つける手順であることです。 たとえば、IPアドレスの完全なリストをテストしたい場合、pingスキャン、つまりオペレーティングシステムのpingコマンドを使用して、IPアドレスを1つずつスキャンするのは非常に時間がかかります。 そのため、pingスイープスクリプトを使用する必要があります。 以下は、pingスイープを使用してライブホストを見つけるためのPythonスクリプトです-

import os
import platform

from datetime import datetime
net = input("Enter the Network Address: ")
net1= net.split('.')
a = '.'

net2 = net1[0] + a + net1[1] + a + net1[2] + a
st1 = int(input("Enter the Starting Number: "))
en1 = int(input("Enter the Last Number: "))
en1 = en1 + 1
oper = platform.system()

if (oper == "Windows"):
   ping1 = "ping -n 1 "
elif (oper == "Linux"):
   ping1 = "ping -c 1 "
else :
   ping1 = "ping -c 1 "
t1 = datetime.now()
print ("Scanning in Progress:")

for ip in range(st1,en1):
   addr = net2 + str(ip)
   comm = ping1 + addr
   response = os.popen(comm)

   for line in response.readlines():
      if(line.count("TTL")):
         break
      if (line.count("TTL")):
         print (addr, "--> Live")

t2 = datetime.now()
total = t2 - t1
print ("Scanning completed in: ",total)

上記のスクリプトは3つの部分で機能します。 最初にIPアドレスの範囲を選択し、pingスイープスキャンを複数の部分に分割します。 次に、オペレーティングシステムに応じてpingスイープのコマンドを選択する関数を使用します。最後に、ホストに関する応答とスキャンプロセスの完了にかかった時間を示します。

出力

上記のスクリプトは、次の出力を生成します-

Enter the Network Address: 127.0.0.1
Enter the Starting Number: 1
Enter the Last Number: 100

Scanning in Progress:
Scanning completed in: 0:00:02.711155

上記の出力は、ファイアウォールがオンになっており、ICMPインバウンド設定も無効になっているため、ライブポートを示していません。 これらの設定を変更すると、出力で提供される1〜100の範囲のライブポートのリストを取得できます。

TCPスキャンを使用するポートスキャナー

TCP接続を確立するには、ホストはスリーウェイハンドシェイクを実行する必要があります。 アクションを実行するには、次の手順に従ってください-

ステップ1-SYNフラグが設定されたパケット

このステップでは、接続を開始しようとしているシステムは、SYNフラグが設定されたパケットで開始します。

ステップ2-SYN-ACKフラグが設定されたパケット

このステップでは、ターゲットシステムはSYNフラグとACKフラグが設定されたパケットを返します。

ステップ3-ACKフラグが設定されたパケット

最後に、開始システムは、ACKフラグが設定された元のターゲットシステムにパケットを返します。

それでも、ここで生じる問題は、ICMPエコー要求および応答メソッド(pingスイープスキャナー)を使用してポートスキャンを実行できる場合、なぜTCPスキャンが必要なのかということです。 その背後にある主な理由は、ICMP ECHO応答機能をオフにするか、ICMPパケットに対してファイアウォールを使用すると、pingスイープスキャナーが機能せず、TCPスキャンが必要になると想定しているためです。

import socket
from datetime import datetime
net = input("Enter the IP address: ")
net1 = net.split('.')
a = '.'

net2 = net1[0] + a + net1[1] + a + net1[2] + a
st1 = int(input("Enter the Starting Number: "))
en1 = int(input("Enter the Last Number: "))
en1 = en1 + 1
t1 = datetime.now()

def scan(addr):
   s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   socket.setdefaulttimeout(1)
   result = s.connect_ex((addr,135))
   if result == 0:
      return 1
   else :
      return 0

def run1():
   for ip in range(st1,en1):
      addr = net2 + str(ip)
      if (scan(addr)):
         print (addr , "is live")

run1()
t2 = datetime.now()
total = t2 - t1
print ("Scanning completed in: " , total)

上記のスクリプトは3つの部分で機能します。 IPアドレスの範囲を選択し、pingスイープスキャンを複数の部分に分割します。 これに続いて、アドレスをスキャンする機能を使用し、さらにソケットを使用します。 後で、ホストに関する応答とスキャンプロセスの完了にかかった時間を示します。 結果= s。 connect_ex((addr、135))ステートメントは、エラーインジケーターを返します。 操作が成功した場合、エラーインジケータは0になります。それ以外の場合、errno変数の値になります。 ここでは、ポート135を使用しました。このスキャナーはWindowsシステムで動作します。 ここで機能する別のポートは445(Microsoft-DSActive Directory)で、通常は開いています。

出力

上記のスクリプトは、次の出力を生成します-

Enter the IP address: 127.0.0.1
Enter the Starting Number: 1
Enter the Last Number: 10

127.0.0.1 is live
127.0.0.2 is live
127.0.0.3 is live
127.0.0.4 is live
127.0.0.5 is live
127.0.0.6 is live
127.0.0.7 is live
127.0.0.8 is live
127.0.0.9 is live
127.0.0.10 is live
Scanning completed in: 0:00:00.230025

効率を向上させるスレッドポートスキャナー

上記のケースで見たように、ポートスキャンは非常に遅くなる可能性があります。 たとえば、ソケットポートスキャナーの使用中に50〜500のポートをスキャンするのにかかる時間は452.3990001678467であることがわかります。 速度を向上させるために、スレッド化を使用できます。 以下は、スレッドを使用したポートスキャナーの例です-

import socket
import time
import threading

from queue import Queue
socket.setdefaulttimeout(0.25)
print_lock = threading.Lock()

target = input('Enter the host to be scanned: ')
t_IP = socket.gethostbyname(target)
print ('Starting scan on host: ', t_IP)

def portscan(port):
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   try:
      con = s.connect((t_IP, port))
      with print_lock:
         print(port, 'is open')
      con.close()
   except:
      pass

def threader():
   while True:
      worker = q.get()
      portscan(worker)
      q.task_done()

q = Queue()
   startTime = time.time()

for x in range(100):
   t = threading.Thread(target = threader)
   t.daemon = True
   t.start()

for worker in range(1, 500):
   q.put(worker)

q.join()
print('Time taken:', time.time() - startTime)

上記のスクリプトでは、Pythonパッケージに組み込まれているスレッドモジュールをインポートする必要があります。 スレッドロックの概念* thread_lock = threading.Lock()*を使用して、一度に複数の変更を行わないようにします。 基本的に、threading.Lock()は、一度に1つのスレッドが変数にアクセスできるようにします。 したがって、二重の変更は発生しません。

後で、ワーカーforループから作業(ポート)をフェッチする1つのthreader()関数を定義します。 次に、portscan()メソッドを呼び出してポートに接続し、結果を出力します。 ポート番号はパラメーターとして渡されます。 タスクが完了すると、q.task_done()メソッドが呼び出されます。

上記のスクリプトを実行すると、50〜500ポートのスキャン速度の違いがわかります。 わずか1.3589999675750732秒しかかかりませんでした。これは、同じ数のlocalhostのポートをスキャンするためにソケットポートスキャナーが費やす時間である452.3990001678467よりも非常に短い時間です。

出力

上記のスクリプトは、次の出力を生成します-

Enter the host to be scanned: localhost
Starting scan on host: 127.0.0.1
135 is open
445 is open
Time taken: 1.3589999675750732