[Python]Pythonとセキュリティ – ②Pythonで作る ポートスキャニング ツール

はじめに

前回([Python] Pythonとセキュリティ – ①Pythonとは)でPythonの概要や特徴について調べてみた。
今回はPythonを利用した簡単な ポートスキャニングツール を作ってみよう。
また、ツールを利用することで不用意に動作しているサービスを確認して対応することが出来る。

情報を収集する行為である「Banner Grabbing」になるため、許可を得ていない対象に実施するのは犯罪です。当該の記事で問題が発生した場合、弊社では一切責任を負い兼ねますのでご了承ください。

Port Scan( ポートスキャン )とは?

ポートスキャンは対象のサーバーもしくはネットワーク機器などに対してオープンしているポートを検索し、識別することである。オープンしているポートを確認することで、対象から起動しているサービスの確認ができ、攻撃者にとってはポートスキャンが攻撃のための事前準備とも言える。

Port Scanの種類は以下のものがある

  • UDP Port Scan
  • TCP Port Scan
  • Connect Scan
    • Half-open(SYN) Scan
    • FIN / NULL / Xmas Scan

Port Scan( ポートスキャン )種類と特徴

UDP Port Scan

UDP Scanの場合は、UDPプロトコルを利用してポートをスキャンする。ポートがオープンされている場合、対象からは応答はないが、クローズされている場合は、ICMPメッセージ(Destination Unreachable, Port Unreachable)の応答がある。但し、UDP Scanはルータやファイアウォールからパケットが損失される可能性が高いため、信頼性は低い。

UDP ポートスキャン

TCP Connect Scan(TCP Open Scan)

connect()関数を利用して、対象と3 Way-Handshakingを結び、オープンされているポートを確認するスキャン。信頼性が高くて、rootと権限がなくてもスキャンを行えるが、スキャンの速度が遅く、ログが残る。
TCPコネクト ポートスキャン

TCP Half-Open Scan(SYN Stealth Scan)

SYNスキャンとも呼ばれるHalf-Open Scanは、TCP Connect Scanとは違って、3 Way-Handshakingで完全なセッションは結ばず、SYNパケットのみ利用してポートを確認する。ログは残らないが、実施のため、root権限が必要である。
TCPハーフオープン ポートスキャン

root権限が必要な理由?
TCPプロトコルのヘッダーの制御ビットの設定が必要なため、root権限じゃないとSYNスキャンは実行できない。
ログが残らない理由?
対象からSYN/ACKの応答を受信したら、応答としてACKではなく、RSTに設定したパケットを送信する。
RSTのパケットのため、通信が強制に終了されてしまい、通信設定が最後まで(セッションを結ぶ)行わなかったため、システムにログが残らない可能性が高い。

FIN/NULL/Xmas Scan

三つのスキャンはFlagをFINに設定するTCP FIN Scan, 何も設定しないNULL Scan, FIN, PSH, HUGを同時に設定するXmas Scanがある。
それぞれ正常な通信ではないため、ログが残らない、対象がUNIX/Linux環境のみ使える、また、Open/Filter/エラーの結果が不明である特徴を持っている。

FIN Scan

FIN スキャン

NULL Scan

NULL スキャン

Xmas Scan

Xmas スキャン

socketモジュールを利用してPythonでScanningツールを作ってみよう

socketモジュールをインポート後、connect()関数を利用し、IPとPort番号を指定したら、TCP通信を行う。send(), recv()関数を利用してデータの送信、受信が可能である。

import socket
s = socket.socket()
s.connect(('IPアドレス', ポート番号))
s.close()
#portがオープンされている場合
>> 
#portがオープンされていない場合
Traceback (most recent call last):
  File "C:/~", line 3, in <module>
    s.connect(('127.0.0.1', 23))
ConnectionRefusedError: [WinError 10061] 対象のコンピューターによって拒否されたため、接続できませんでした。

エラーを解決するために、簡単な方法で「try」と「except」文を利用して成功と失敗に対してそれぞれ区別する。

import socket
try:
s = socket.socket()
s.connect(('IPアドレス', ポート番号))
    print('success')
    s.close()
except:
    print('fail')
#portがオープンされている場合
>> success
#portがオープンされていない場合
>> fail

roop文を利用して範囲内のポート番号を自動で確認するように作る。

import socket
for port in range(1,101):
    try:
        s = socket.socket()
        s.connect(('IPアドレス', port))
        print('オープンされているポート:%d' % port)
        s.close()

    except: pass
>> オープンされているポート:22
>> オープンされているポート:80

1から100までのポートを確認するのは、時間がかかるので、Pythonのリストデータ型を利用して、主に使用されているポートのみスキャンしてみよう。

良く使用されるポート
20, 21(FTP) / 22(SSH) / 23(Telnet) / 25(SMTP) / 53(DNS) / 80(HTTP) / 110(POP3) / 123(NTP) / 443(HTTPS) / 1433(MSSQL) / 3306(MYSQL) / 1521(ORACLE) / 8080(ORACLE, TOMCAT) / 3389(RDP)

import socket
ports = [20, 21, 22, 23, 25, 53, 80, 110, 123, 443, 1433, 3306, 1521, 8080, 3389]
for port in ports:
    try:
        s = socket.socket()
        s.connect(('IPアドレス', port))
        print('オープンされているポート:%d' % port)
        s.close()

    except: pass
>> オープンされているポート:80
>> オープンされているポート:443
>> オープンされているポート:3306
>> オープンされているポート:8080

input()関数を利用して、ホストアドレスを入力し、ポートスキャニングを実施するコードを作ってみよう。

import socket
ports = [20, 21, 22, 23, 25, 53, 80, 110, 123, 443, 1433, 3306, 1521, 8080, 3389]
host = input('IPアドレス:')
for port in ports:
    try:
        s = socket.socket()
        s.connect((host, port))
        print('オープンされているポート:%d' % port)
        s.close()

    except: pass
>> IPアドレス:127.0.0.1
>> オープンされているポート:80
>> オープンされているポート:443
>> オープンされているポート:3306
>> オープンされているポート:8080

まとめ

今回はPythonのsokectライブラリを利用して簡単なポートスキャニングツールを作ってみたが、これを実務的に使うためには色々修正が必要である。
但し、ポートスキャンの原理、またPythonで基本的なポートスキャンのツールが作れるので、担当者及び管理者はこの投稿を参考して、より安全なネットワーク環境の構築に役に立てればと思っている。

記事まとめ

2020年02月14日 – :sunny:[Python] Pythonとセキュリティ – ①Pythonとは

セキュリティトレンドやITトレンド、
お知らせなどを配信。

Share:

More Posts

コメント*
お名前*
メールアドレス*

コメント*

お名前*
メールアドレス*

Copyright 2020 © CYBERFORTRESS, INC. All rights Reserved.
Scroll Up