С чего начина­ется ата­ка на сер­вер? Пра­виль­но, с раз­ведки! Ска­неров пор­тов сущес­тву­ет мно­жес­тво, и они быс­тро и эффектив­но справ­ляют­ся со сво­ей задачей. Но нас­тоящий хакер дол­жен понимать, как работа­ют его любимые инс­тру­мен­ты, так что сегод­ня мы в учеб­ных целях напишем собс­твен­ный ска­нер, и я рас­ска­жу, какие методы ска­ниро­вания луч­ше никог­да не исполь­зовать.

Сна­чала мы изу­чим теоре­тичес­кую часть: как вооб­ще работа­ет соеди­нение, как оно уста­нав­лива­ется и как мож­но исполь­зовать эти механиз­мы. Тут я покажу «пло­хую» реали­зацию ска­нера. Затем мы раз­берем ска­нер здо­рово­го челове­ка и реали­зуем его самос­тоятель­но.

 

Теория

Для начала пос­мотрим, как сетевые устрой­ства вза­имо­дей­ству­ют друг с дру­гом в клас­сичес­ком слу­чае. Для это­го исполь­зуют­ся сокеты, которые упро­щен­но мож­но изоб­разить как тру­бы. При этом у каж­дой тру­бы два кон­ца — это и есть сокеты. Один конец тру­бы находит­ся на одном компь­юте­ре, дру­гой — на дру­гом, а прог­раммы могут что‑то помещать в такие «тру­бы» или читать из них.

Су­щес­тву­ет два типа сокетов: TCP и UDP. Они отли­чают­ся тем, что про­исхо­дит в пути от одно­го кон­ца тру­бы к дру­гому. TCP-сокет гаран­тиру­ет, что пакеты будут дос­тавле­ны до дру­гого кон­ца тру­бы в нуж­ном поряд­ке и без потерь — если это вооб­ще воз­можно, разуме­ется. А вот UDP-сокеты работа­ют на ско­рость и могут потерять или перепу­тать пакеты по дороге.

Наглядное объяснение
Наг­лядное объ­ясне­ние

Ви­деос­вязь, нап­ример, отлично исполь­зует пре­иму­щес­тва UDP. Если с каналом вдруг что‑то не так, какие‑то пакеты прос­то потеря­ются, а оставши­еся дой­дут в срок, и какая‑никакая кар­тинка все рав­но будет.

 

Пишем сканер на сокетах

Этот ска­нер — самый прос­той и оче­вид­ный. Что­бы узнать, какие пор­ты откры­ты, мож­но прос­то поп­робовать под­клю­чить­ся к ним пооче­ред­но и пос­мотреть, что будет.

Все при­меры кода при­вожу на Python 3.10, а работать я пред­почитаю в PyCharm, хотя и не навязы­ваю тебе свой выбор.

Соз­даем прог­рамму и импорти­руем основные модули:

import socket
from datetime import datetime
import sys

www

Под­робнее узнать о работе с модулем socket мож­но в офи­циаль­ной докумен­тации.

За­пом­ним вре­мя запус­ка прог­раммы — в даль­нейшем это при­годит­ся, что­бы узнать вре­мя ска­ниро­вания.

start = datetime.now()

Хра­нить пары из пор­тов и наз­ваний сер­висов будем пря­мо в коде. При желании можешь про­апгрей­дить этот метод, нап­ример до фай­лов JSON.

ports = {
20: "FTP-DATA", 21: "FTP", 22: "SSH", 23: "Telnet",
25: "SMTP", 43: "WHOIS", 53: "DNS", 80: "http",
115: "SFTP", 123: "NTP", 143: "IMAP", 161: "SNMP",
179: "BGP", 443: "HTTPS", 445: "MICROSOFT-DS",
514: "SYSLOG", 515: "PRINTER", 993: "IMAPS",
995: "POP3S", 1080: "SOCKS", 1194: "OpenVPN",
1433: "SQL Server", 1723: "PPTP", 3128: "HTTP",
3268: "LDAP", 3306: "MySQL", 3389: "RDP",
5432: "PostgreSQL", 5900: "VNC", 8080: "Tomcat", 10000: "Webmin" }

Пре­обра­зуем передан­ный аргу­мент в IP-адрес. Для это­го скор­мим пер­вый аргу­мент коман­дной стро­ки нашего ска­нера фун­кции socket.gethostbyname(string) — бонусом получим раз­решение DNS, если переда­но домен­ное имя, а не IP-адрес.

host_name = sys.argv[1]
ip = socket.gethostbyname(host_name)

Те­перь в цик­ле обой­дем все пор­ты из спис­ка и про­верим воз­можность под­клю­чения к ним. Если порт зак­рыт, будет вызывать­ся исклю­чение, которое мы перех­ватим, и прог­рамма не вылетит.

В кон­це работы сох­раня­ем вре­мя окон­чания и выводим на экран дли­тель­ность ска­ниро­вания.

for port in ports:
cont = socket.socket()
cont.settimeout(1)
try:
cont.connect((ip, port))
except socket.error:
pass
else:
print(f"{socket.gethostbyname(ip)}:{str(port)} is open/{ports[port]}")
cont.close()
ends = datetime.now()
print("<Time:{}>".format(ends - start))
input("Press Enter to the exit....")

Те­перь, что­бы про­тес­тировать работу нашего ска­нера, откро­ем тер­минал, перей­дем в пап­ку со ска­нером и выпол­ним коман­ду

python.exe socket.py 45.33.32.156

info

Ес­ли ты работа­ешь на Linux, исполь­зуй коман­ду python3, что­бы слу­чай­но не нар­вать­ся на уста­рев­ший Python.

Са­мо собой, вмес­то IP в при­мере мож­но ука­зать любой хост.

Да­вай пос­мотрим, как это выг­лядит со сто­роны сер­вера. Для это­го вос­поль­зуем­ся ста­рич­ком Netcat. Ска­чай его и запус­ти сле­дующим обра­зом:

ncat.exe -lnvp 123

warning

Netcat может понадо­бить­ся внес­ти в белый спи­сок анти­виру­са или сог­ласовать уста­нов­ку с кор­поратив­ной служ­бой безопас­ности. Netcat час­то исполь­зуют хакеры, что­бы под­нять шел­лы в ском­про­мети­рован­ных сис­темах, так что ругань анти­виру­са впол­не оправдан­на.

В сосед­нем тер­минале запус­каем наш ска­нер изу­чать наш собс­твен­ный IP-адрес. Пос­мотреть его мож­но в выводе коман­ды ipconfig /all. В резуль­тате в окне с Netcat про­изой­дет сле­дующее.

Реакция Netcat на сканирование
Ре­акция Netcat на ска­ниро­вание

На скрин­шоте вид­но, что было уста­нов­лено пол­ноцен­ное соеди­нение, и, конеч­но, в реаль­нос­ти любая прог­рамма тоже это уви­дит, то есть незамет­но прос­каниро­вать кого‑то таким обра­зом не получит­ся.

Так­же давай теперь прос­каниру­ем сер­вер scanme.nmap.org (имен­но его IP был в пер­вом при­мере). Резуль­таты будут выг­лядеть при­мер­но так:

Address: 45.33.32.156
45.33.32.156:22 is open/SSH
45.33.32.156:80 is open/http

Ска­нер нашел два откры­тых пор­та — 22 и 80. Но если прос­каниро­вать этот же хост при помощи Nmap, уви­дим, что откры­тых пор­тов нам­ного боль­ше.

Nmap scan report for scanme.nmap.org (45.33.32.156)
Host is up (0.22s latency).
Not shown: 994 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
1720/tcp open h323q931
5060/tcp open sip
9929/tcp open nping-echo
31337/tcp open Elite
Nmap done: 1 IP address (1 host up) scanned in 5.02 seconds

По­чему так? Nmap про­ходит по зна­читель­но боль­шему спис­ку пор­тов, чем наш ска­нер, и, соот­ветс­твен­но, видит боль­ше. Если мы добавим эти пор­ты в наш ска­нер, он тоже их най­дет.

По­нят­но, что такой ска­нер вряд ли при­меним в реаль­ных усло­виях, кро­ме сов­сем уж экзо­тичес­ких: нап­ример, ког­да ска­ниро­вать надо с машины, на которую невоз­можно дос­тавить пол­ноцен­ный ска­нер, но на которой уже есть Python.

Да­вай луч­ше поп­робу­ем сде­лать ска­нер, который не ста­нет так палить­ся и работать будет куда быс­трее.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    19 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии