Our Blog

Сканер портов на PHP

Сканер портов на PHP позволяет узнать какие порты открыты на сервере, а значит, какие службы на нем работают.

Что представляет собой сканер портов на PHP? Чтобы узнать, открыт порт или нет, необходимо попытаться к нему подключиться. Если подключение произошло удачно, то на удаленном сервере какая-либо служба открыла этот порт в ожидании подключений. Если подключение неудачно, то порт закрыт. Чтобы остаться невидимым, чаще всего взломщик захватывает какой-либо Web-сервер в Интернете, устанавливает на него свой сценарий и производит сканирование с этого сервера, оставаясь при этом анонимным. Давайте посмотрим пример сценария, который сканирует первые 1024 порта:

<?php
for ($i=1; $i<=1024; $i++) {
  $s=socket_create(AF_INET, SOCK_STREAM, 0);
  $res=@socket_connect($s, "127.0.0.1", $i);
  if ($res)
  print("<P> Порт открыт $i");
}
?>

Вот такой небольшой фрагмент кода помогает хакеру получить достаточно много информации об удаленном компьютере. Пример работы сценария:
Порт открыт 21 (ftp)
Порт открыт 22 (ssh)
Порт открыт 80 (http)
Теперь посмотрим, что происходит в сценарии. Запускаем цикл, который будет выполняться от 1 до 1024 раз. Внутри цикла создается сокет с помощью функции socket_create(). Сканироваться будут порты интернет протокола TCP, поэтому в качестве первого параметра передаем AF_INET (указывает на необходимость использования интернет-протокола). Второй параметр равен SOCK_STREAM, ЧТО соответствует семейству протоколов TCP Третий параметр обнулен. На следующем этапе пытаемся соединиться с портом $i с помощью функции socket_connect(). Если соединение невозможно, то функция вернет ошибку, которая будет отображена на форме. Чтобы подавить сообщение об ошибке, перед именем функции поставим символ @ Результат выполнения функции сохраняется в переменной $res. Теперь проверим результат. Если он равен true, то порт открыт, поэтому выводим на экран соответствующее сообщение. Вы должны учитывать, что такое сканирование далеко не всегда верно. Крупные сайты имеют достаточно интеллектуальные средства предотвращения сканирования.
Усложним задачу. Давайте сделаем так, чтобы IP-адрес определялся в коде сценария, т. е. чтобы пользователь мог передавать имя компьютера. Помимо этого, будем отображать не только номер открытого порта, но и его имя. Рассмотрим пример такого сценария:

<?php
$host_ip = gethostbyname("www.yahoo.com");
for ($i=l; $i<=100; $i++) {
  $s=socket_create(AF_INET, SOCK_STREAM, 0 );
  $res=@socket_connect($s, $host_ip, $i);
  if ($res){
    $portname=getservbyport($ i, "tcp");
    print("<P> Порт открыт $i ($portname)");
  }
}
?>

Результат выполнения сценария:
Порт открыт 21 (ftp)
Порт открыт 22 (ssh)
Порт открыт 80 (http)
В этом примере, прежде чем выполнять цикл, мы определяем IP-адрес указанного компьютера с помощью функции gethostbyname(). Если пользователь укажет не имя компьютера, а его адрес, то функция ничего преобразовывать не будет, а просто вернет этот же IP. Так как мы в цикле соединяемся с одним и тем же компьютером, то чтобы не определять имя на каждом шаге, вызов функции gethostbynameo вынесен за пределы цикла. Когда найден открытый порт, мы определяем его имя с помощью функции getservbyport (). Этой функции передается номер найденного порта и имя протокола tcp, потому что мы сканируем именно эти порты.
А вот сканет UDP-портов, тут всего два отличия от ТСР-сканирования:
• У функции socket_create () второй параметр равен SOCK_DGRAM, ЧТО соответствует UDP-протоколу.
• При определении имени службы у функции getservbyport () второй параметр равен udp.

<?php
$host_ip = gethostbyname("www.yahoo.com");
for ($i=l; $i<=100; $i++){
   $s=socket_create(AF_INET, SOCK_DGRAM, 0 );
   $res=8socket_connect($s, $host_ip, $i);
   if ($res){
      $portname=getservbyport($i, "udp");
      print("<P> Порт открыт $i ($portname)");
   }
}
?>

Наш сканер портов не оптимизирован, и я считаю, что его надо оптимизировать. Цикл выполняется 1024 раза, и каждый раз мы создаем сокет с помощью функции socket_create (). Это отнимает лишние ресурсы сервера и время, а ведь сокет нужно создавать до начала цикла и после успешного соединения с сервером. Если соединение прошло неудачно, то можно без вызова socket_create() пытаться подключиться на другой порт. Вот оптимизированный вариант сканирования:
Оптимизированный Сканер портов на PHP

<?php
$host_ip = gethostbyname("www.yahoo.com");
$s=socket_create(AF_INET, SOCK_STREAM, 0 );
for ($i=l; $i<=100; $i++){
   $res=@socket_connect($s, $host_ip, $i);
   if ($res) {
      $portname=getservbyport($i, "tcp");
      print("<p> Порт открыт $i ($portname)");
      $s=socket_create(AF_INET, SOCK_STREAM, 0);
   }
}
?>

Теперь создание сокета будет происходить ровно столько раз, сколько открыто портов, плюс 1.

Comments ( 0 )
    -->