• Strona główna
  • Curriculum Vitae
  • O mnie
  • Mapa strony
  • Kontakt
Niebieski Pomarańczowy Zielony Różowy Fioletowy

Wykrywanie typu serwera HTTP

Opublikowane 5 marca 2010. Autor: Kamil Brenk. Wizyt: 1 311.

Kategorie: JavaScript
Tematyka: Apache, bezpieczeństwo stron www, JavaScript, Microsoft IIS, praktyczne skrypty, Wyrażenia regularne

mar 05

Chciałbym zaprezentować tutaj pewną ciekawostkę z zakresu bezpieczeństwa stron internetowych. W jaki sposób wykryć typ serwera zdalnego? Do wyboru mamy kilka serwerów, typu Apache, Microsoft IIS, Lighttpd czy nginx? W poście tym zaprezentuję sposób na identyfikację tylko dwóch pierwszych.

W jaki sposób wykryć serwer po stronie klienta?

Nie potrzeba żadnych specjalistycznych narzędzi i metod, by móc wykryć rodzaj serwera HTTP używanego przez inne strony internetowe. Sposób na wykrywanie serwera nie wymagający żadnych zewnętrznych programów zostanie przedstawiony w tym poście.

Stwórzmy na szybko obiekt służący do późniejszego wyciągania informacji o zdalnych serwerach HTTP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
 *
 * @author Kamil Brenk
 * @support kontakt@kamilbrenk.pl
 *
 * Detect Server Name
 * Class to detect server name: Apache or IIS in JavaScript
 *
 * HOWTO:
 * detectServer.loadImages('http://www.blog.kamilbrenk.pl/');
 * window.setTimeout(function() {
 *  ds = detectServer.init();
 *  ds.page_url     // http://blog.kamilbrenk.pl
 *  ds.server_name  // Apache
 * }, 500);
 *
**/

var detectServer = {

    /**
    *
    * Initialization and manage all operations
    *
    * @return object                returns: page url and server name
    *
    **/

    init: function() {
       
        // set default value for server name
        this.server_name = 'niezidentyfikowany';
       
        // check validate url
        if ( !this.checkUrl() ) {
            alert('Proszę podać prawidowy adres!');
            return {
           
                page_url:       '-',
                server_name:    '-'
           
            };
        }
       
        // delete last slash in url
        this.deleteSlashInURL();
       
        // check server type
        this.checkServerType();
       
        // return results
        return {
       
            page_url:       this.detect_url,
            server_name:    this.server_name
       
        };
       
    },
   
   
   
    /**
    *
    * Check server type
    * loops through the properties of an object (servers type)
    *
    **/

    checkServerType: function() {
   
        for (var img in this.images) {
           
            // check image size
            if (
                this.images[img].width === this.servInfo[img].image.width &&
                this.images[img].height === this.servInfo[img].image.height
            ) {
                this.server_name = this.servInfo[img].name;
            }
       
        }
   
    },
   
   
    /**
    *
    * Load all images
    *
    * @param string detect_url      full url to server (only domain)
    *
    **/

    loadImages: function(detect_url) {
   
        // set url
        this.detect_url = detect_url;
   
        // object with created images
        this.images = {};
   
        for (var i in this.servInfo) {
       
            // create new image object
            var new_req = new Image();
                new_req.src = this.detect_url + this.servInfo[i].image.src;
           
            // bind new object image
            this.images[i] = new_req;
       
        }
   
    },
   
   
    /**
    *
    * Check valid Url
    *
    * @return string        return result of validation
    *
    **/

    checkUrl: function() {
   
        // valid url regex
        // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
        var _validUrl = /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
   
        // return result
        return _validUrl.test(this.detect_url);
   
    },
   
   
    /**
    *
    * Delete last slash in URL
    * if exist
    *
    **/

    deleteSlashInURL: function() {
   
        // check if exist
        if (this.detect_url.charAt(this.detect_url.length-1) !== '/') return false;
       
        // delete
        this.detect_url = this.detect_url.substring(0, this.detect_url.length-1);
   
    },
   
   
   
    /**
    *
    * Servers Info
    * for: Apache, IIS
    *
    **/

    servInfo: {
   
        apache: {
       
            name: 'Apache',
            image: {
                src:        '/icons/tar.gif',
                width:      20,
                height:     22
            }
           
        },
       
        IIS: {
       
            name: 'Microsoft IIS',
            image: {
                src:        '/pageerror.gif',
                width:      36,
                height:     48
            }
       
        }
   
    }

}

Obiekt ten zawiera kilka metod:

  • init – inicjalizacja i kontrola nad pobieraniem nazw serwerów HTTP; wewnętrzne zarządzanie kolejnymi metodami,
  • checkServerType – właściwa metoda sprawdzająca typ serwera HTTP,
  • loadImages – dynamiczne wczytanie obrazków wymagane do sprawdzenia typu serwera,
  • checkUrl – wyrażenie regularne przeprowadzające test adresu Url strony, której typ serwera ma zostać sprawdzony,
  • deleteSlashInURL – prosta metoda usuwająca ostatni slash (/) z adresu Url, jeśli takowy istnieje,
  • servInfo – obiekt przechowujący dane specyficzne dla różnych serwerów.

Teraz wystarczy odpalić powyższy obiekt i pobrać dane dotyczące serwera HTTP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
window.onload = function() {
   
    // load all images
    detectServer.loadImages('http://www.kamilbrenk.pl/');

    // ..when images are loaded
    window.setTimeout(function() {
   
        // detect server type
        var detect_server = detectServer.init();
       
        // show page url
        document.getElementById('pageUrl').innerHTML = detect_server.page_url;
   
        // show result detect
        document.getElementById('servName').innerHTML = detect_server.server_name;
       
    }, 500);

}

Zastosowałem tutaj window.setTimeout, aby skrypt zdążył wysłać request do obrazków, a dopiero po chwili wykonał sprawdzenie przebiegu wczytywania. Można by to napisać dużo zgrabniej, jednak na powyższe potrzeby raczej nie jest to konieczne.

Jak to działa?

Gdy już poznaliśmy metody wykorzystywane przez obiekt, mogę wyjaśnić sposób, w jaki jest określany typ serwera HTTP.

Otóż specyficzną cechą dla serwera Apache jest posiadanie obrazu pod adresem /icons/tar.gif, który powinien mieć wymiary 20x22px. Cechą szczególną serwera Microsoft IIS jest grafika pod adresem /pageerror.gif o wymiarach 36x48px. I już mamy klucz do ciekawego określania typu serwera.

Wyczytałem także, iż router bezprzewodowy Linksys WRK54-G ma obraz /UI_Linksys.gif o wymiarach 165x57px.

No więc powyższy obiekt tworzy dynamicznie obrazki próbujące w celu sprawdzenia, czy wymiary i ścieżki się zgadzają. Jeśli się zgadzają to bardzo prawdopodobne jest, iż mamy do czynienia z określonym serwerem HTTP. Oczywiście można zabronić dostępu do wybranych plików i folderów na serwerze, lecz większość o tym zapomina (lub po prostu nie wie).

Tutaj rodzi się pytanie, czy inne serwery posiadają również takie luki bezpieczeństwa wskazujące na typ używanego serwera HTTP? Jeśli ktoś wie to byłbym wdzięczny za info :-)

Gdzie czyha niebezpieczeństwo?

Otóż głównym niebezpieczeństwem w tym przypadku jest fakt, iż znając używane oprogramowanie przez serwer zewnętrzny możemy wyszukać w Internecie popularnych luk bezpieczeństwa i wykrytych już błędów, a następnie przeprowadzić atak na taki serwis.

W końcu nie każdy aktualizuje swoje serwerowe oprogramowanie na bieżąco, więc jest duże prawdopodobieństwo, że wykryta już luka bezpieczeństwa jest naprawiona w najnowszej wersji serwera, jednak aktualnie wykorzystywana przez providera jest wciąż podatna na dany atak. Określenie typu serwera HTTP i sprawdzenie popularnych luk bezpieczeństwa jest dobrym punktem rozpoczęcia zabawy hakera.

Inne sposoby wykrycia serwera HTTP

Owszem, wykryć typ serwera HTTP można na kilka sposobów – poprzez skrypty działające po stronie serwera (PHP, .NET, Python), poprzez programy zewnętrzne (telnet), jak i przy pomocy „sztuczek” po stronie klienta (o tym już było).

Po stronie serwera (PHP) można to zrobić następująco:

1
2
3
4
5
6
$get = get_headers('http://testy-zawodowe.pl/', true);
echo $get['Server'];

/**
 * Result: Apache/2.2.8 (Ubuntu) mod_ssl/2.2.8 OpenSSL/0.9.8g
**/

Metoda ta jest dużo prostsza, jednak nie wszystkie serwisy odsyłają typ serwera w nagłówku.

Słowem zakończenia

Jak widać, haker ma wiele możliwości określenia rodzaju serwera HTTP. Przed wszystkimi tymi metodami istnieją sposoby obrony, także miejmy nadzieję, że notka ta okaże się pomocna w wykrywaniu potencjalnych metod pobierania typu serwera HTTP, a następnie ich blokowaniu, bowiem nie powinniśmy dopuszczać, by klient posiadał takie informacje.

Wykrywanie typu serwera HTTP – pokaż przykład

Mała uwaga:
Post ten ma charakter edukacyjny, a celem jest uświadamiane twórców stron o zagrażających im niebezpieczeństwach.

Podobne wpisy

  • Kompresja JavaScript
  • Boilerplate 2.0
  • Kompendium programisty #2
  • Jak załadować biblioteki JavaScript?
  • Recenzja: JavaScript – mocne strony

Komentarze (3)

  1. karpio 24 sierpnia 2010

    Typ serwera można wykryć w łatwiejszy sposób, poprzez analizę zwracanych nagłówków http. Większość serwerów przesyła nagłówek o nazwie „server” w którym znajduje się…. nazwa serwera web :) np. „Server: Microsoft-IIS/7.5″. Można to łatwo sprawdzić narzędziem typu Fiddler.

    pozdrawiam
    karpio

  2. Kamil Brenk 24 sierpnia 2010

    @karpio: podałem rozwiązanie od strony serwera, czytaj wyżej (nagłówek Inne sposoby wykrycia serwera HTTP)

    By the way, sposobów jest wiele, ja jednak tutaj zaprezentowałem dość nietypowe i możliwe do przeprowadzenia od strony klienta – ot zwykła ciekawostka :-)

  3. karpio 25 sierpnia 2010

    mea culpa. nie doczytałem ;)



Dodaj komentarz

XHTML: Możesz użyć następujących tagów
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Kamil Brenk Blog

PHP, JavaScript, SQL, HTML

  • Informacje o blogu

    Kamil Brenk

    Blog o tworzeniu aplikacji na potrzeby sieci Web.

    Praktyczne przykłady, porady i sztuczki. PHP, SQL, AJAX, JavaScript, HTML i pochodne.

    Kanał RSS

    • Najnowsze
    • Komentarze
    • Popularne
    • Gramatyka w HTML i CSS
    • PHP kontra Microsoft Office, part I
    • Cross-Domain JavaScript: CORS
    • Wysyłanie wiadomości SMS w PHP
    • Boilerplate 2.0
    • Własne selektory w jQuery
    • Kamil Brenk: @Michał:1) jak już otrzymam dyplom to zrobię serię o...
    • Michal Wachowski: Po pierwsze - tyle czekania i tylko to? A bu! :) Po drugie -...
    • Kamil Brenk: @CapaciousCore: języki kompilowane są szybsze niż...
    • CapaciousCore: @Kamil Brenk wiem, że komentarze i post nie są uber świeże....
    • Kamil Brenk: @CapaciousCore: post i komentarze napisane ponad rok temu;...
    • CapaciousCore: Przebrnąłem przez te wszystkie komentarze i mam trochę...
    • Kamil Brenk: @arhiman: dzięki za komentarz :)A to dziwne co piszesz, bo...
    • Przyszłość PHP
    • Niestandardowe czcionki na stronie
    • Gramatyka w PHP, część 1
    • Umowa i zaliczka dla freelancera
    • Projekt aplikacji po stronie klienta
    • Własny mechanizm Feed
    • jQuery.extends dla PHP
  • Szukajka
    Wpisz co chcesz wyszukać na stronie…
  • Kategorie
    • Apache
    • Freelancer
    • Front-end Development
    • HTML5 & CSS3
    • Inne
    • JavaScript
    • Książki
    • PHP
    • Po godzinach
    • Pozycjonowanie
    • Protokół HTTP
    • SQL
    • Wyrażenia regularne
  • Moje serwisy
    • Testy zawodowe
    • Miłość, uczucia i seks
  • Czytane blogi
    • Wojciech Sznapka
    • Wojciech Soczyński
    • Michał Wachowski
    • Tomasz Kowalczyk
    • JavaScript po polsku | Code42
  • Archiwum
    • Luty 2012
    • Listopad 2011
    • Październik 2011
    • Wrzesień 2011
    • Sierpień 2011
    • Lipiec 2011
    • Maj 2011
    • Kwiecień 2011
    • Marzec 2011
    • Luty 2011
    • Styczeń 2011
    • Grudzień 2010
    • Listopad 2010
    • Październik 2010
    • Wrzesień 2010
    • Sierpień 2010
    • Lipiec 2010
    • Czerwiec 2010
    • Maj 2010
    • Kwiecień 2010
    • Marzec 2010
    • Luty 2010
    • Styczeń 2010
  • Strona główna
  • Curriculum Vitae
  • O mnie
  • Mapa strony
  • Kontakt

Kamil Brenk © 2010. All rights reserved.

Designed by FTL Wordpress Themes brought to you by Smashing Magazine.

Do góry ∧