BOOK THIS SPACE FOR AD
ARTICLE ADİnternet iletişimlerinin çoğu HTTP protokolü aracılığıyla web istekleri ile yapılır. HTTP, World Wide Web kaynaklarına erişmek için kullanılan uygulama düzeyinde bir protokoldür.
HTTP iletişimi, bir istemci ve bir sunucu arasında gerçekleşen bir protokoldür. İstemci, sunucudan bir kaynak talep eder ve sunucu bu talebi işleyerek istenen kaynağı geri gönderir. Varsayılan bağlantı noktası genellikle 80 veya 8080'dir, ancak web sunucusu yapılandırmasına bağlı olarak değiştirilebilir. Bu iletişim, farklı web sitelerini ziyaret ettiğimizde aynı temel HTTP taleplerini kullanarak gerçekleşir.
Requests And Responses (İstekler ve Yanıtlar)
Bir web sitesine eriştiğimizde, tarayıcınızın HTML, Görüntüler gibi varlıklar için bir web sunucusuna istekte bulunması ve yanıtları indirmesi gerekecektir. Bundan önce, tarayıcıya özellikle bu kaynaklara nasıl ve nereden erişeceğini söylemeniz gerekir, URL’ler burada yardımcı olacaktır.
URL
URL, bir kaynağın tam konumunu belirten bir metin dizisidir.
Bir URL, kaynağın protokolünü (HTTP, HTTPS, FTP, vb.), sunucunun adresini (IP adresi veya FQDN), port numarasını (isteğe bağlı) ve kaynağın yolunu içerebilir.Örnek bir URL: https://www.example.com:8080/index.htmlURL, bir kaynağa erişmek için gerekli olan tüm bilgileri içerir.URL ve FQDN farkı
URL : https://www.example.com:8080/index.html
FQDN : www.example.com
FQDN
FQDN, bir internet alan adının tam ve kesin bir şekilde belirtilmiş hali olarak düşünülebilir.Bir FQDN, alan adını belirten bir ana etki alanı (örneğin, “example.com”) ve bu alanın alt etki alanları (subdomain) ile birleştirilen tam bir adresi ifade eder.Örnek bir FQDN: www.example.comFQDN, IP adresine çevrildiğinde, belirli bir sunucunun tam adresini belirler.FQDN : Fully Qualified Domain Name
URL : Uniform Resource Locator
URL
HTTP üzerinden kaynaklara, ziyaret etmek istediğimiz bir web sitesini belirtmekten çok daha fazla özellik sunan bir URL aracılığıyla erişilir. URL’nin yapısı :
Scheme : ( http:// https:// ) Bu, client tarafından erişilen protokolü tanımlamak için kullanılır ve iki nokta üst üste ve çift eğik çizgi (://) ile biter.
User Info : ( admin:password@ ) Bu, ana bilgisayara kimlik doğrulaması yapmak için kullanılan kimlik bilgilerini (iki nokta üst üste : ile ayrılmış) içeren isteğe bağlı bir bileşendir ve ana bilgisayardan bir at işareti (@) ile ayrılır.
Host : ( example.com ) Ana bilgisayar, kaynak konumunu belirtir. Bu bir ana bilgisayar adı veya IP adresi olabilir
Port : (80) Port, Host’tan iki nokta üst üste (:) ile ayrılır. Herhangi bir bağlantı noktası belirtilmezse, http şemaları varsayılan olarak 80 numaralı bağlantı noktasını ve https varsayılan olarak 443 numaralı bağlantı noktasını kullanır
Path : (/dashboard.php ) Bu, erişilen kaynağa işaret eder; bu bir dosya veya klasör olabilir. Herhangi bir yol belirtilmezse, sunucu varsayılan dizini döndürür (örn. index.html).
Query String : ( ?login=true ) Sorgu dizesi bir soru işareti (?) ile başlar ve bir parametre (örn. login) ile bir değerden (örn. true) oluşur. Birden fazla parametre bir ve işareti (&) ile ayrılabilir.
Fragments : ( #status ) Fragmanlar, birincil kaynak içindeki bölümleri (örneğin sayfadaki bir başlık veya bölüm) bulmak için istemci tarafındaki tarayıcılar tarafından işlenir.
Bir kaynağa erişmek için tüm bileşenler gerekli değildir. Ana zorunlu alanlar scheme ve host’tur, bunlar olmadan istekte bulunulacak kaynak olmaz.
Bir kullanıcı tarayıcıya URL’yi (inlanefreight.com) ilk kez girdiğinde, domain’i çözümlemek ve IP’sini almak için bir DNS (Domain Name Resolution) sunucusuna bir istek gönderir. DNS sunucusu inlanefreight.com için IP adresini arar ve geri döndürür. Bir sunucu IP adresi olmadan iletişim kuramayacağı için tüm domainleri bu şekilde çözümlenmesi gerekir.
Not: Tarayıcılarımız genellikle ilk olarak yerel ‘/etc/hosts’ dosyasındaki kayıtlara bakar ve istenen alan adı bu dosyada yoksa diğer DNS sunucularıyla iletişime geçer. IP’yi ve ardından alan adını ekleyerek DNS çözümlemesi için kayıtları manuel olarak eklemek için ‘/etc/hosts’ dosyasını kullanabiliriz.
Tarayıcı, istenen domaine bağlı IP adresini aldığında, varsayılan HTTP bağlantı noktasına (örneğin 80) bir GET isteği göndererek root / path’i sorar. Ardından, web sunucusu isteği alır ve işler. Varsayılan olarak, sunucular / için bir istek alındığında bir dizin dosyası döndürecek şekilde yapılandırılmıştır. (Genellikle /index.html sayfasıdır.)
Bu durumda, index.html dosyasının içeriği okunur ve web sunucusu tarafından HTTP yanıtı olarak döndürülür. Yanıt, isteğin başarıyla işlendiğini gösteren durum kodunu da (örneğin 200 OK) içerir. Web tarayıcısı daha sonra index.html içeriğini işler ve kullanıcıya sunar.
cURL
Komut satırı tabanlı bir veri transfer aracıdır. cURL, URL’ler aracılığıyla veri iletimi yapma yeteneğine sahiptir ve birçok farklı protokolü destekler. Bu protokoller arasında HTTP, HTTPS, FTP, FTPS, SCP, SFTP, LDAP, ve daha birçokları bulunmaktadır.
cURL’ü kullanarak, komut satırından bir web sunucusuna istek gönderebilir, dosyalar indirebilir veya yükleyebilir, çeşitli ağ protokollerini kullanarak veri transferi yapabilirsiniz. cURL, birçok işletim sistemi üzerinde çalışabilir ve bir dizi seçenekle birlikte kullanılabilir.
Aşağıdaki gibi, cURL için bir argüman olarak kullanarak herhangi bir URL’ye temel bir HTTP isteği gönderebiliriz:
cURL’ün bir web tarayıcısından farklı olarak HTML/JavaScript/CSS kodunu render etmediğini, ancak ham formatında yazdırdığını görüyoruz.
cURL’ü bir sayfayı veya dosyayı indirmek ve -O bayrağını kullanarak içeriği bir dosyaya çıktı olarak almak için de kullanabiliriz. Eğer çıktı dosyasının ismini belirtmek istiyorsak -o bayrağını kullanabilir ve ismi belirtebiliriz. Aksi takdirde, -O’yu kullanabiliriz ve cURL aşağıdaki gibi uzaktaki dosya adını kullanacaktır:
M1R4CKCK@htb[/htb]$ curl -O inlanefreight.com/index.htmlM1R4CKCK@htb[/htb]$ ls
index.html
Son olarak, cURL ile başka hangi seçenekleri kullanabileceğimizi görmek için -h bayrağını kullanabiliriz:
cURL kılavuz sayfasının tamamını görüntülemek için man curl kullanabiliriz.
Makine Çözümü 1-
Soru : Bayrağı almak için yukarıdaki alıştırmayı başlatın, ardından yukarıda gösterilen sunucuda ‘/download.php’ tarafından döndürülen dosyayı indirmek için cURL kullanın.
Cevap : -O parametresi ile indiriyoruz .
Hypertext Transfer Protocol Secure (HTTPS)
Ancak, HTTP’nin önemli dezavantajlarından biri, tüm verilerin açık metin olarak aktarılmasıdır. Bu, kaynak ve hedef arasındaki herhangi birinin aktarılan verileri görüntülemek için Ortadaki Adam (MiTM) saldırısı gerçekleştirebileceği anlamına gelir.
Bu soruna karşı koymak için HTTPS (HTTP Secure) protokolü oluşturuldu, bu protokolde tüm iletişim şifreli bir biçimde aktarılır, böylece üçüncü bir taraf isteği engellese bile, verileri çıkaramaz
HTTPS’ye Genel Bakış
Bir HTTP isteğini incelersek, bir web tarayıcısı ile bir web uygulaması arasında güvenli iletişimi zorunlu kılmamanın etkisini görebiliriz. Örneğin, bir HTTP oturum açma isteğinin içeriği aşağıdadır:
Örnek bir wireshark çıktısı :
Oturum açma kimlik bilgilerinin açık metin olarak görüntülenebildiğini görebiliriz. Bu, aynı ağdaki birinin (herkese açık bir kablosuz ağ gibi) isteği yakalamasını ve kimlik bilgilerini kötü amaçlı olarak yeniden kullanmasını kolaylaştıracaktır.
Buna karşılık, birisi HTTPS isteğinden gelen trafiği yakalayıp analiz ettiğinde aşağıdaki gibi bir şey görecektir:
Gördüğümüz gibi, veriler tek bir şifrelenmiş akış olarak aktarılır, bu da herhangi birinin kimlik bilgileri veya diğer hassas veriler gibi bilgileri ele geçirmesini çok zorlaştırır.
HTTPS uygulayan web siteleri, URL’lerindeki https:// (örneğin https://www.medium.com) ve web tarayıcısının adres çubuğunda URL’nin solundaki kilit simgesiyle tanımlanabilir:
Dolayısıyla, Medium gibi HTTPS kullanan bir web sitesini ziyaret edersek, tüm trafik şifrelenecektir.
HTTPS Akışı
HTTPS’nin yüksek seviyede nasıl çalıştığına bakalım:
HTTPS uygulayan bir web sitesini ziyaret etmek için https:// yerine http:// yazarsak, tarayıcı domainini çözümlemeye çalışır ve kullanıcıyı hedef web sitesini barındıran web sunucusuna yönlendirir. İlk olarak şifrelenmemiş HTTP protokolü olan 80 numaralı bağlantı noktasına bir istek gönderilir. Sunucu bunu algılar ve istemciyi bunun yerine güvenli HTTPS bağlantı noktası 443'e yönlendirir. Bu, ilerideki bir bölümde tartışacağımız 301 Moved Permanently yanıt kodu aracılığıyla yapılır.
Ardından, client (web tarayıcısı) kendisi hakkında bilgi veren bir “ client hello” paketi gönderir. Bundan sonra, sunucu “server hello” ile yanıt verir ve ardından SSL sertifikalarını değiştirmek için bir anahtar değişimi yapılır. Client anahtarı/sertifikayı doğrular ve kendi sertifikasını gönderir. Bundan sonra, şifrelemenin ve aktarımın doğru çalışıp çalışmadığını onaylamak için şifreli bir el sıkışma (handshake) başlatılır.
Not: Koşullara bağlı olarak, bir saldırgan HTTPS iletişimini HTTP’ye düşüren ve aktarılan verileri açık metin haline getiren bir HTTP düşürme saldırısı gerçekleştirebilir. Bu, kullanıcının bilgisi olmadan tüm trafiği saldırganın ana bilgisayarı üzerinden aktarmak için bir Man-In-The-Middle (MITM) proxy’si kurarak yapılır. Ancak çoğu modern tarayıcı, sunucu ve web uygulaması bu saldırıya karşı koruma sağlar. (HTTP düşürme saldırısı hedef web siteye HTTPS’den HTTP ‘ye düşürerek MITM saldırısı yapmaktır.)
HTTPS için cURL
cURL tüm HTTPS iletişim standartlarını otomatik olarak ele almalı ve güvenli bir el sıkışma gerçekleştirmeli ve ardından verileri otomatik olarak şifrelemeli ve şifresini çözmelidir. Ancak, geçersiz veya güncel olmayan bir SSL sertifikasına sahip bir web sitesiyle iletişime geçersek, cURL varsayılan olarak daha önce bahsedilen MITM saldırılarına karşı koruma sağlamak için iletişime devam etmeyecektir:
cURL ile sertifika kontrolünü atlamak için -k bayrağını kullanabiliriz:
M1R4CKCK@htb[/htb]$ curl -k https://inlanefreight.com<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
...SNIP...
HTTP İstekleri ve Yanıtları (Requests and Responses)
HTTP iletişimleri temel olarak bir HTTP isteği (request) ve bir HTTP yanıtından(response) oluşur. Bir HTTP isteği client (örn. cURL/tarayıcı) tarafından yapılır ve sunucu (örn. web sunucusu) tarafından işlenir.
HTTP Request
URL’ye yapılan bir HTTP GET isteğini göstermektedir:
http://inlanefreight.com/users/login.htmlHerhangi bir HTTP isteğinin ilk satırı ‘boşluklarla ayrılmış’ üç ana alan içerir:Method (GET) : Gerçekleştirilecek eylem türünü belirten HTTP yöntemi veya fiili.Path (/users/login.html) :Erişilen kaynağa giden yol. Bu alana bir sorgu dizesi de eklenebilir (örn. ?username=user).Version HTTP/1.1 : Üçüncü ve son alan HTTP sürümünü belirtmek için kullanılır.Sonraki satır kümesi Host, User-Agent, Cookie ve diğer birçok olası başlık gibi HTTP başlık değer eşlerini içerir. Bu header’lar (başlıklar) bir isteğin çeşitli niteliklerini belirtmek için kullanılır. Headerlar, sunucunun isteği doğrulaması için gerekli olan yeni bir satırla sonlandırılır. Son olarak, bir request, request body ve data ile bitebilir.
Not: HTTP sürüm 1.X istekleri açık metin olarak gönderir ve farklı alanları ve farklı istekleri ayırmak için yeni satır karakteri kullanır. HTTP sürüm 2.X ise istekleri sözlük biçiminde ikili veri olarak gönderir.
HTTP Yanıtı (Response)
Sunucu isteğimizi işledikten sonra yanıtını gönderir. Aşağıda örnek bir HTTP yanıtı verilmiştir:
Bir HTTP yanıtının ilk satırı boşluklarla ayrılmış iki alan içerir. Bunlardan ilki HTTP sürümü(version) (örn. HTTP/1.1), ikincisi ise HTTP yanıt (response) kodudur (örn. 200 OK).
İlk satırdan sonra yanıt, HTTP isteğine benzer şekilde başlıklarını listeler.
Son olarak yanıt, başlıklardan sonra yeni bir satırla ayrılan bir yanıt gövdesiyle sona erebilir. Yanıt gövdesi genellikle HTML kodu olarak tanımlanır. Ancak JSON gibi diğer kod türleriyle, resimler, stil sayfaları veya komut dosyaları gibi web sitesi kaynaklarıyla ve hatta web sunucusunda barındırılan PDF belgesi gibi bir belgeyle de yanıt verebilir.
cURL
HTTP isteğinin ve yanıtının tamamını görüntülemek için, önceki komutlarımıza -v verbose bayrağını ekleyebiliriz ve hem isteği hem de yanıtı yazdırması gerekir:
M1R4CKCK@htb[/htb]$ curl inlanefreight.com -v* Trying SERVER_IP:80...
* TCP_NODELAY set
* Connected to inlanefreight.com (SERVER_IP) port 80 (#0)
> GET / HTTP/1.1
> Host: inlanefreight.com
> User-Agent: curl/7.65.3
> Accept: */*
> Connection: close
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Date: Tue, 21 Jul 2020 05:20:15 GMT
< Server: Apache/X.Y.ZZ (Ubuntu)
< WWW-Authenticate: Basic realm="Restricted Content"
< Content-Length: 464
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
...SNIP...
Gördüğümüz gibi, bu sefer HTTP isteğinin ve yanıtının tamamını alıyoruz. İstek basitçe Host, User-Agent ve Accept başlıklarıyla birlikte GET / HTTP/1.1 gönderdi. Buna karşılık, HTTP yanıtı HTTP/1.1 401 Unauthorized’ı içeriyordu, bu da ilerideki bir bölümde göreceğimiz gibi istenen kaynak üzerinde erişimimiz olmadığını gösterir.
Not: -vvv bayrağı daha da ayrıntılı bir çıktı gösterir. (Fakat -v parametresinden hemen hemen farksızdır.)
Browser DevTools
Çoğu modern web tarayıcısı, esas olarak geliştiricilerin web uygulamalarını test etmeleri için tasarlanmış yerleşik geliştirici araçlarıyla (DevTools) birlikte gelir.
Chrome ya da Firefox’ta tarayıcı geliştirme araçlarını açmak için [CTRL+SHIFT+I] tuşlarına ya da sadece [F12] tuşuna tıklayabiliriz. Devtools, her birinin kendi kullanımı olan birden fazla sekme içerir. Web isteklerinden sorumlu olduğu için bu modülde çoğunlukla Network sekmesine odaklanacağız.
Gördüğümüz gibi, devtools bize bir bakışta yanıt durumunu (yani yanıt kodu), kullanılan istek yöntemini (GET), istenen kaynağı (yani URL / alan adı) ve istenen yolu gösterir. Ayrıca, web sitesinin çok fazla istek yüklemesi durumunda, belirli bir isteği aramak için Filtre URL’lerini kullanabiliriz.
Soru : İstek ele geçirilirken kullanılan HTTP yöntemi nedir? (büyük/küçük harfe duyarlı)
Cevap : GET
Soru : Yukarıdaki sunucuya bir GET isteği gönderin ve sunucuda çalışan Apache sürümünü bulmak için yanıt başlıklarını okuyun, ardından bunu yanıt olarak gönderin. (cevap formatı: X.Y.ZZ)
Cevap : 2.4.41
HTTP Headers (Başlıklar)
1.General Headers (Genel Başlıklar)
2.Entity Headers (Varlık Başlıkları)
3.Request Headers (İstek Başlıkları)
4.Response Headers (Cevap Başlıkları)
5.Security Headers (Güvenlik Başlıkları)
General Headers (Genel Başlıklar)Genel başlıklar hem HTTP isteklerinde hem de yanıtlarında kullanılır. Bağlamsaldırlar ve içeriğinden ziyade mesajı tanımlamak için kullanılırlar.
Date : (Date: Wed, 16 Feb 2022 10:38:44 GMT ) : İletinin kaynaklandığı tarih ve saati tutar. Saati standart UTC zaman dilimine dönüştürmek tercih edilir.
Connection : (Connection: close) : İstek bittikten sonra geçerli ağ bağlantısının canlı kalıp kalmayacağını belirtir. Bu başlık için yaygın olarak kullanılan iki değer close ve keep-alive’dır. Client veya sunucudan gelen close değeri bağlantıyı sonlandırmak istedikleri anlamına gelirken, keep-alive başlığı bağlantının daha fazla veri ve girdi almak için açık kalması gerektiğini belirtir. (Örnek bir tatil web sitesinde search kısmına herhangi bir şehir girince web sitesi adresi değişmeden o şehirdeki konaklama yerlerini göstermesi.)
General Headers diğer tüm parametleri tıklayın.
2.Entity Headers (Varlık Başlıkları)
Genel başlıklara benzer şekilde, Varlık Başlıkları hem istek hem de yanıt için ortak olabilir. Bu başlıklar, bir mesaj tarafından aktarılan içeriği (varlık) tanımlamak için kullanılır. Genellikle yanıtlarda ve POST veya PUT isteklerinde bulunurlar.
Content-Type : (Content-Type: text/html) : Aktarılan kaynağın türünü tanımlamak için kullanılır. Değer, client tarafındaki tarayıcılar tarafından otomatik olarak eklenir ve sunucu yanıtında döndürülür. Charset alanı, UTF-8 gibi kodlama standardını belirtir.
Media-Type : (Media-Type: application/pdf) : Media-type, Content-Type’a benzer ve aktarılan veriyi tanımlar. Bu başlık, sunucunun girdimizi yorumlamasında çok önemli bir rol oynayabilir. Charset alanı da bu başlıkla birlikte kullanılabilir.
Boundary : (boundary=”b4e4fbd93540" ) : Aynı mesajda birden fazla içerik olduğunda içeriği ayırmak için bir işaretleyici görevi görür. Örneğin, bir form verisi içinde, formun farklı bölümlerini ayırmak için bu sınır header tarafından — b4e4fbd93540 olarak kullanılır.
Content-Length : (Content-Length: 385) :Aktarılan varlığın boyutunu tutar. Bu başlık, sunucu mesaj gövdesinden veri okumak için kullandığından gereklidir ve tarayıcı ve cURL gibi araçlar tarafından otomatik olarak oluşturulur.
Content-Encoding : (Content-Encoding: gzip ) :Veriler iletilmeden önce birden fazla dönüşümden geçebilir. Örneğin, mesaj boyutunu azaltmak için büyük miktarda veri sıkıştırılabilir. Kullanılan kodlama türü Content-Encoding başlığı kullanılarak belirtilmelidir.
3.Request Headers
Client bir HTTP işleminde Request Headers (İstek Başlıkları) gönderir. Bu başlıklar bir HTTP isteğinde kullanılır ve mesajın içeriğiyle ilgili değildir. Aşağıdaki başlıklar HTTP isteklerinde yaygın olarak görülür.
Host : (Host: www.example.com) : Kaynak için sorgulanan hostu belirtmek için kullanılır. Bu bir domain veya IP adresi olabilir. HTTP sunucuları,host adına göre ortaya çıkan farklı web sitelerini barındıracak şekilde yapılandırılabilir. Bu, host başlığını önemli bir numaralandırma hedefi haline getirir, çünkü hedef sunucuda başka ana bilgisayarların varlığını gösterebilir.
User-Agent : (User-Agent: curl/7.77.0) : User-Agent başlığı, kaynakları talep eden client’i tanımlamak için kullanılır. Bu başlık, tarayıcı, sürümü ve işletim sistemi gibi istemci hakkında birçok şeyi ortaya çıkarabilir. (Bunu değiştirebiliriz client tarafı biz olduğumuz için karşı tarafın bizim bilgilerimizi öğrenmemizi bazen istemeyebiliriz . Fakat public ip ‘miz gizli olması kadar önemli değildir. Bug Buanty için ise ikisi bile önemli olmayabilir . Hedef web sitenin çizdiği kurallara uyduğumuz sürece.)
Referer : (Referer: http://www.google.com/ ) : Geçerli isteğin nereden geldiğini belirtir. Örneğin, Google arama sonuçlarından bir bağlantıya tıklamak https://google.com adresini yönlendirici yapar. Bu başlığa güvenmek tehlikeli olabilir çünkü kolayca manipüle edilebilir ve istenmeyen sonuçlara yol açabilir.
Accept : (Accept: */* ) : Accept başlığı, istemcinin hangi medya türlerini anlayabileceğini açıklar. Virgülle ayrılmış birden fazla ortam türü içerebilir. */* değeri, tüm medya türlerinin kabul edildiğini belirtir. İşaretini ”*/*” görmek bizi mutlu edebilir . Çünkü saldırı potansiyelini genişletebilir bu konu bir sonraki yazılarımız da değinilecektir.
Cookie : (Cookie: PHPSESSID=b4e4fbd93540) : name=value biçiminde cookie-value çiftleri içerir. Cookie, client tarafında ve sunucuda depolanan ve bir tanımlayıcı görevi gören bir veri parçasıdır. Bunlar her istekte sunucuya aktarılır, böylece clientin erişimi korunur. Cookiler, kullanıcı tercihlerini kaydetme veya oturum izleme gibi başka amaçlara da hizmet edebilir. Tek bir başlıkta noktalı virgülle ayrılmış birden fazla cookie olabilir.
Authorization : (Authorization: BASIC cGFzc3dvcmQK) : Sunucunun istemcileri tanımlaması için başka bir yöntem. Başarılı bir kimlik doğrulamasından sonra, sunucu cliente özgü bir belirteç döndürür. Tanımlama bilgilerinin aksine, belirteçler yalnızca client tarafında saklanır ve her istekte sunucu tarafından alınır. Kullanılan web sunucusuna ve uygulama türüne bağlı olarak birden fazla kimlik doğrulama türü vardır.
4.Response Headers
Response Headers (Yanıt Başlıkları) bir HTTP yanıtında kullanılabilir ve içerikle ilgili değildir. Age (Yaş), Location (Konum) ve Server (Sunucu) gibi belirli yanıt başlıkları, yanıt hakkında daha fazla bağlam sağlamak için kullanılır. Aşağıdaki başlıklar HTTP yanıtlarında yaygın olarak görülür.
Server : (Server: Apache/2.2.14 (Win32)) : İsteği işleyen HTTP sunucusu hakkında bilgi içerir. Sunucu hakkında sürüm gibi bilgiler edinmek ve daha fazla numaralandırmak (enumaration) için kullanılabilir.
WWW-Authenticate : (WWW-Authenticate: BASIC realm=”localhost”) : Cliente , istenen kaynağa erişmek için gereken kimlik doğrulama türünü bildirir.
5.Security Headers
Son olarak, Güvenlik Başlıklarımız var. Tarayıcı çeşitliliğinin ve web tabanlı saldırıların artmasıyla birlikte, güvenliği artıran belirli başlıkların tanımlanması gerekli hale geldi. HTTP Güvenlik başlıkları, web sitesine erişirken tarayıcı tarafından izlenecek belirli kuralları ve politikaları belirtmek için kullanılan bir yanıt başlıkları sınıfıdır.
Content-Security-Policy : (Content-Security-Policy: script-src ‘self’) : Web sitesinin harici olarak enjekte edilen kaynaklara yönelik politikasını belirler. Bu JavaScript kodunun yanı sıra komut dosyası kaynakları da olabilir. Bu başlık, tarayıcıya yalnızca belirli güvenilir alanlardan gelen kaynakları kabul etmesi talimatını verir ve böylece Siteler Arası Komut dosyası oluşturma (XSS) gibi saldırıları önler.
Strict-Transport-Security : (Strict-Transport-Security: max-age=31536000) : Tarayıcının web sitesine düz metin HTTP protokolü üzerinden erişmesini engeller ve tüm iletişimin güvenli HTTPS protokolü üzerinden yapılmasını zorunlu kılar. Bu, saldırganların web trafiğini koklamasını (sniffing) ve parolalar veya diğer hassas veriler gibi korunan bilgilere erişmesini önler.
Referrer-Policy : (Referrer-Policy: origin): Tarayıcının Referer başlığı aracılığıyla belirtilen değeri dahil edip etmeyeceğini belirler. Web sitesinde gezinirken hassas URL’lerin ve bilgilerin ifşa edilmesini önlemeye yardımcı olabilir.
cURL
Eğer sadece yanıt başlıklarını görmek istiyorsak, HEAD isteği göndermek ve sadece yanıt başlıklarını görüntülemek için -I bayrağını kullanabiliriz. Ayrıca, hem başlıkları hem de yanıt gövdesini (örneğin HTML kodu) görüntülemek için -i bayrağını kullanabiliriz. İkisi arasındaki fark, -I bir HEAD isteği gönderirken (bir sonraki bölümde göreceğimiz gibi), -i belirttiğimiz herhangi bir isteği gönderir ve başlıkları da yazdırır.
Örnek :
M1R4CKCK@htb[/htb]$ curl -I https://www.inlanefreight.comHost: www.inlanefreight.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko)
Cookie: cookie1=298zf09hf012fh2; cookie2=u32t4o3tb3gg4
Accept: text/plain
Referer: https://www.inlanefreight.com/
Authorization: BASIC cGFzc3dvcmQK
Date: Sun, 06 Aug 2020 08:49:37 GMT
Connection: keep-alive
Content-Length: 26012
Content-Type: text/html; charset=ISO-8859-4
Content-Encoding: gzip
Server: Apache/2.2.14 (Win32)
Set-Cookie: name1=value1,name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT
WWW-Authenticate: BASIC realm="localhost"
Content-Security-Policy: script-src 'self'
Strict-Transport-Security: max-age=31536000
Referrer-Policy: origin
-H bayrağı ile istek başlıklarını ayarlamamıza da izin verir. User-Agent veya Cookie başlıkları gibi bazı başlıkların kendi bayrakları vardır. Örneğin, User-Agent’ımızı ayarlamak için -A’yı aşağıdaki gibi kullanabiliriz:
→ H (header) ve -A (user-agent) flag’leri, cURL komut satırı aracında farklı amaçlar için kullanılan iki ayrı bayraktır.
-H (header):
-H bayrağı, HTTP isteğine ek başlıklar eklemek için kullanılır.Başlık eklemek istediğinizde, bu bayrağı kullanır ve ardından eklemek istediğiniz başlık değerini belirtirsiniz.Örneğin: curl -H "Content-Type: application/json" -H "Authorization: Bearer your_access_token" https://api.example.com/dataBu komut, “Content-Type” ve “Authorization” başlıklarını içeren bir HTTP isteği gönderir.-A veya — user-agent (user-agent):
-A bayrağı, sadece User-Agent başlığını belirlemek için kullanılır.User-Agent başlığı, tarayıcı veya isteği gönderen uygulamanın bilgisini içerir.Örneğin: curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" https://example.comBu komut, sadece User-Agent başlığını belirtilen değerle birlikte içeren bir HTTP GET isteği gönderir.M1R4CKCK@htb[/htb]$ curl https://www.inlanefreight.com -A 'Mozilla/5.0'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
...SNIP...
Browser DevTools
Son olarak, tarayıcı devtools’unu kullanarak HTTP başlıklarını nasıl önizleyebileceğimizi görelim. Önceki bölümde yaptığımız gibi, sayfa tarafından yapılan farklı istekleri görüntülemek için Network sekmesine gidebiliriz. Ayrıntılarını görüntülemek için isteklerden herhangi birine tıklayabiliriz:
İlk Headers sekmesinde hem HTTP istek hem de HTTP yanıt başlıklarını görürüz. Devtools başlıkları otomatik olarak bölümler halinde düzenler, ancak ayrıntılarını ham biçimlerinde görüntülemek için Raw düğmesine tıklayabiliriz. Ayrıca, gelecek bölümde tartışılacağı gibi, istek tarafından kullanılan cookieleri görmek için Cookies sekmesini kontrol edebiliriz.
Soru : Yukarıdaki sunucu, sayfa yüklendikten sonra bayrağı yükler. Sayfa tarafından hangi isteklerin yapıldığını görmek ve bayrağa yapılan isteği bulmak için tarayıcı devtools’undaki Ağ sekmesini kullanın.
Cevap : Network Sekmesinden yüklenen istekleri incelediğimizde .txt adlı bir uzantıya sahip olduğunu görüyoruz. Uzantıya gidelim .
HTTP Metotları ve Kodları
HTTP, bir kaynağa erişmek için birden fazla yöntemi destekler. HTTP protokolünde, çeşitli istek yöntemleri tarayıcının sunucuya bilgi, form veya dosya göndermesini sağlar. Bu yöntemler, diğer şeylerin yanı sıra, sunucuya gönderdiğimiz isteği nasıl işleyeceğini ve nasıl yanıtlayacağını söylemek için kullanılır.
Request (İstek) Methods
GET : Belirli bir kaynak ister. URL’deki sorgu dizeleri aracılığıyla sunucuya ek veriler aktarılabilir (örn. ?param=value).
POST : Sunucuya veri gönderir. Metin, PDF ve diğer ikili veri biçimleri gibi birden fazla girdi türünü işleyebilir. Bu veriler, başlıklardan sonra bulunan istek gövdesine eklenir. POST yöntemi genellikle bilgi gönderirken (örn. formlar/loginler) veya bir web sitesine resim veya belge gibi veriler yüklerken kullanılır.
HEAD : Sunucuya bir GET isteği yapıldığında döndürülecek başlıkları ister. İstek gövdesini döndürmez ve genellikle kaynakları indirmeden önce yanıt uzunluğunu kontrol etmek için yapılır.
PUT : Sunucu üzerinde yeni kaynaklar oluşturur. Uygun kontroller olmadan bu yönteme izin vermek, kötü amaçlı kaynakların yüklenmesine yol açabilir.
DELETE: Web sunucusundaki mevcut bir kaynağı siler. Uygun şekilde güvence altına alınmazsa, web sunucusundaki kritik dosyaları silerek Hizmet Reddi’ne (DoS) yol açabilir.
OPTIONS : Sunucu hakkında, sunucu tarafından kabul edilen yöntemler gibi bilgileri döndürür.
PATCH: Belirtilen konumdaki kaynağa kısmi değişiklikler uygular.
Bu liste en yaygın kullanılan HTTP yöntemlerinden sadece birkaçını vurgulamaktadır.
Not: Çoğu modern web uygulaması temel olarak GET ve POST yöntemlerini kullanır. Bununla birlikte, REST API’lerini kullanan herhangi bir web uygulaması, API uç noktasındaki verileri sırasıyla güncellemek ve silmek için kullanılan PUT ve DELETE yöntemlerini de kullanır.
Yanıt Kodları (Response Codes)
HTTP durum kodları, istemciye isteğinin durumunu bildirmek için kullanılır. Bir HTTP sunucusu beş tür yanıt kodu döndürebilir:
1xx : Bilgi sağlar ve talebin işlenmesini etkilemez.
2xx: Bir istek başarılı olduğunda döndürülür.
3xx: Sunucu istemciyi yeniden yönlendirdiğinde döndürülür.
4xx : Client’den gelen uygunsuz istekleri belirtir. Örneğin, mevcut olmayan bir kaynağın talep edilmesi veya kötü bir formatın talep edilmesi.
5xx: HTTP sunucusunun kendisiyle ilgili bir sorun olduğunda döndürülür.
Aşağıda, yukarıdaki HTTP yöntem türlerinin her birinden yaygın olarak görülen örneklerden bazıları verilmiştir:
200 OK : Başarılı bir istek üzerine döndürülür ve yanıt gövdesi genellikle istenen kaynağı içerir.
400 Bad Request : Satır sonlandırıcıları eksik olan istekler gibi hatalı biçimlendirilmiş isteklerle karşılaşıldığında döndürülür.
302 Found : İstemciyi başka bir URL’ye yönlendirir. Örneğin, başarılı bir oturum açma işleminden sonra kullanıcıyı kontrol paneline yönlendirmek gibi.
305 Proxy Kullan (Use Proxy) : Sunucu tarafından döndürülen proxy adresinin kullanılması gerektiğini belirten durum kodudur.
403 Forbidden : İstemcinin kaynağa uygun erişimi olmadığını belirtir. Sunucu, kullanıcıdan kötü amaçlı girdi algıladığında da döndürülebilir.
404 Not Found : Client sunucuda bulunmayan bir kaynağı talep ettiğinde döndürülür.
500 Internal Server Error : Sunucu isteği işleyemediğinde döndürülür.
Standart HTTP yanıt kodlarının tam listesi için bu bağlantıyı ziyaret edebilirsiniz. Standart HTTP kodlarının yanı sıra, Cloudflare veya AWS gibi çeşitli sunucular ve sağlayıcılar kendi kodlarını uygular.
GET
Herhangi bir URL’yi ziyaret ettiğimizde, tarayıcılarımız bu URL’de barındırılan uzak kaynakları elde etmek için varsayılan olarak bir GET isteği gönderir. Tarayıcı talep ettiği ilk sayfayı aldıktan sonra; çeşitli HTTP yöntemlerini kullanarak başka talepler gönderebilir. Bu, önceki bölümde görüldüğü gibi tarayıcı geliştirme araçlarındaki Network sekmesi aracılığıyla gözlemlenebilir.
HTTP Temel Kimlik Doğrulama (HTTP Basic Auth)
Bazı web sitelerini ziyaret ettiğimizde, bizden bir kullanıcı adı ve şifre girmemizi ister. Kullanıcı kimlik bilgilerini doğrulamak için HTTP parametrelerini kullanan normal oturum açma formlarının aksine (örneğin POST isteği), bu tür kimlik doğrulama, web uygulamasıyla doğrudan etkileşime girmeden belirli bir sayfayı / dizini korumak için doğrudan web sunucusu tarafından işlenen basic bir HTTP kimlik doğrulamasını (basic HTTP authentication) kullanır.
Sayfaya erişmek için, bu durumda admin:admin olan geçerli bir kimlik bilgisi çifti girmemiz gerekir:
Kimlik bilgilerini girdikten sonra sayfaya erişim sağlayacağız:
Sayfaya cURL ile erişmeyi deneyelim ve yanıt başlıklarını görüntülemek için -i ekleyelim:
M1R4CKCK@htb[/htb]$ curl -i http://<SERVER_IP>:<PORT>/HTTP/1.1 401 Authorization Required
Date: Mon, 21 Feb 2022 13:11:46 GMT
Server: Apache/2.4.41 (Ubuntu)
Cache-Control: no-cache, must-revalidate, max-age=0
WWW-Authenticate: Basic realm="Access denied"
Content-Length: 13
Content-Type: text/html; charset=UTF-8
Access denied
Gördüğümüz gibi, yanıt gövdesinde Access denied ve WWW-Authenticate başlığında Basic realm=”Access denied” değerlerini alıyoruz, bu da Headers bölümünde tartışıldığı gibi bu sayfanın gerçekten de basic HTTP auth kullandığını doğruluyor. Kimlik bilgilerini cURL aracılığıyla sağlamak için aşağıdaki gibi -u bayrağını kullanabiliriz:
M1R4CKCK@htb[/htb]$ curl -u admin:admin http://<SERVER_IP>:<PORT>/<!DOCTYPE html>
<html lang="en">
<head>
...SNIP...
Bu kez yanıt olarak sayfayı alırız. basic HTTP auth kimlik bilgilerini sağlayabileceğimiz başka bir yöntem daha vardır, bu da doğrudan URL aracılığıyla (kullanıcı adı: password@URL) şeklindedir. Aynı şeyi cURL veya tarayıcımızla denersek, sayfaya da erişebiliriz:
M1R4CKCK@htb[/htb]$ curl http://admin:admin@<SERVER_IP>:<PORT>/<!DOCTYPE html>
<html lang="en">
<head>
...SNIP...
HTTP Authorization Header ( Kimlik Doğrulama Başlıkları)
Daha önceki cURL komutlarımızdan birine -v bayrağını eklersek:
M1R4CKCK@htb[/htb]$ curl -v http://admin:admin@<SERVER_IP>:<PORT>/* Trying <SERVER_IP>:<PORT>...
* Connected to <SERVER_IP> (<SERVER_IP>) port PORT (#0)
* Server auth using Basic with user 'admin'
> GET / HTTP/1.1
> Host: <SERVER_IP>
> Authorization: Basic YWRtaW46YWRtaW4=
> User-Agent: curl/7.77.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 21 Feb 2022 13:19:57 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Cache-Control: no-store, no-cache, must-revalidate
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Pragma: no-cache
< Vary: Accept-Encoding
< Content-Length: 1453
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en">
<head>
...SNIP...
Basic HTTP auth kullandığımız için, HTTP isteğimizin Authorization başlığını admin:admin’in base64 kodlu değeri olan Basic YWRtaW46YWRtaW4= olarak ayarladığını görüyoruz.
Sayfaya erişmemize izin verip vermediğini görmek için kimlik bilgilerini sağlamadan Authorization’ı manuel olarak ayarlamayı deneyelim. Header bayrağı (-H) ile ayarlayabiliriz ve yukarıdaki HTTP isteğindeki aynı değeri kullanacağız. Birden fazla başlık belirtmek için -H bayrağını birden fazla kez ekleyebiliriz:
M1R4CKCK@htb[/htb]$ curl -H 'Authorization: Basic YWRtaW46YWRtaW4='http://<SERVER_IP>:<PORT>/
<!DOCTYPE html
<html lang="en">
<head>
...SNIP...
Gördüğümüz gibi, bu da bize sayfaya erişim sağladı. Bunlar sayfaya kimlik doğrulaması yapmak için kullanabileceğimiz birkaç yöntemdir. Çoğu modern web uygulaması, kullanıcıların kimliklerini doğrulamak için HTTP POST isteklerini kullanan ve ardından kimlik doğrulamalarını sürdürmek için bir cookie döndüren backend komut dosyası dili (örneğin PHP) ile oluşturulmuş oturum açma formlarını kullanır.
GET Parametreleri
Kimliğimiz doğrulandıktan sonra, bir arama terimi girebileceğimiz ve eşleşen şehirlerin bir listesini alabileceğimiz bir City Search işlevine erişebiliriz:
Sayfa sonuçlarımızı döndürürken, bilgileri almak için uzak bir kaynakla iletişim kuruyor ve ardından bunları sayfada görüntülüyor olabilir. Bunu doğrulamak için, tarayıcı devtools’u açabilir ve Network sekmesine gidebiliriz . Arama terimimizi girmeden ve istekleri görüntülemeden önce, önceki istekleri temizlediğimizden ve yalnızca daha yeni istekleri izlediğimizden emin olmak için sol üstteki çöp kutusu simgesine tıklamamız gerekebilir:
Bundan sonra, herhangi bir arama terimi girip enter tuşuna basabiliriz ve backend’e yeni bir istek gönderildiğini hemen fark ederiz:
İsteğe tıkladığımızda, URL’de kullanılan GET parametresi search=le ile search.php’ye gönderilir. Bu, arama fonksiyonunun sonuçlar için başka bir sayfa talep ettiğini anlamamıza yardımcı olur.
Şimdi, arama sonuçlarının tamamını almak için aynı isteği doğrudan search.php’ye gönderebiliriz, ancak muhtemelen yukarıdaki ekran görüntüsünde gösterilen HTML düzenine sahip olmadan bunları belirli bir biçimde (örneğin JSON) döndürecektir.
cURL ile bir GET isteği göndermek için, GET istekleri parametrelerini URL’ye yerleştirdiğinden, yukarıdaki ekran görüntülerinde görülen URL’nin aynısını kullanabiliriz. Ancak, tarayıcı geliştirme araçları cURL komutunu elde etmek için daha uygun bir yöntem sağlar. İsteğe sağ tıklayabilir ve Copy>Copy as cURL seçeneğini seçebiliriz. Ardından, kopyalanan komutu terminalimize yapıştırabilir ve çalıştırabiliriz ve tam olarak aynı yanıtı almalıyız:
M1R4CKCK@htb[/htb]$ curl 'http://<SERVER_IP>:<PORT>/search.php?search=le'-H 'Authorization: Basic YWRtaW46YWRtaW4='
Leeds (UK)
Leicester (UK)
Not: Kopyalanan komut HTTP isteğinde kullanılan tüm başlıkları içerecektir. Ancak, bunların çoğunu kaldırabilir ve yalnızca Authorization başlığı gibi gerekli kimlik doğrulama başlıklarını tutabiliriz.
Aynı isteği doğrudan tarayıcı devtools’u içinde Copy>Copy as Fetch’i seçerek de tekrarlayabiliriz. Bu, JavaScript Fetch kütüphanesini kullanarak aynı HTTP isteğini kopyalayacaktır. Ardından, [CTRL+SHIFT+K] tuşlarına tıklayarak JavaScript konsol sekmesine gidebilir, Fetch komutumuzu yapıştırabilir ve isteği göndermek için enter tuşuna basabiliriz:
Gördüğümüz gibi, tarayıcı isteğimizi gönderdi ve ardından dönen yanıtı görebiliyoruz.
Soru : Yukarıdaki alıştırma yanlış sonuçlar döndürdüğü için bozuk gibi görünüyor. Arama yaptığımızda gönderdiği isteğin ne olduğunu görmek için tarayıcı devtools’u kullanın ve ‘flag’ araması yapmak ve bayrağı elde etmek için cURL kullanın.
Cevap : Network kısmından copy>copy as curl yapalım ve isteğimizi düzenleyip terminale yazalım .
POST
Web uygulamalarının dosya aktarması veya kullanıcı parametrelerini URL’den taşımaması gerektiğinde, POST isteklerini kullanırlar.
Kullanıcı parametrelerini URL içine yerleştiren HTTP GET’in aksine, HTTP POST kullanıcı parametrelerini HTTP İstek gövdesi içine yerleştirir. Bunun üç ana faydası vardır:
Günlük Kaydı Eksikliği : POST istekleri büyük dosyaları aktarabileceğinden (örn. dosya yükleme), sunucunun GET isteği ile yüklenen bir dosyada olduğu gibi yüklenen tüm dosyaları istenen URL’nin bir parçası olarak günlüğe kaydetmesi verimli olmayacaktır.Daha fazla veri gönderilebilir: Maksimum URL Uzunluğu tarayıcılar (Chrome/Firefox/IE), web sunucuları (IIS, Apache, nginx), İçerik Dağıtım Ağları (Fastly, Cloudfront, Cloudflare) ve hatta URL Kısaltıcılar (bit.ly, amzn.to) arasında değişir. Genel olarak, bir URL’nin uzunluğu 2.000 karakterin altında tutulmalıdır ve bu nedenle çok fazla veri işleyemezler.Daha Az Kodlama Gereksinimi: URL’ler paylaşılmak üzere tasarlanmıştır, bu da harflere dönüştürülebilen karakterlere uymaları gerektiği anlamına gelir. POST isteği, ikili verileri kabul edebilen gövdeye veri yerleştirir. Kodlanması gereken tek karakter, parametreleri ayırmak için kullanılan karakterlerdir.Login Forms
Web uygulamasını ziyaret ettiğimizde, HTTP basic auth yerine bir PHP giriş formu kullandığını görüyoruz:
Eğer admin:admin ile giriş yapmaya çalışırsak, GET bölümünde daha önce gördüğümüze benzer bir arama fonksiyonu görürüz:
Tarayıcı devtools’umuzdaki Network sekmesini temizler ve tekrar giriş yapmayı denersek, birçok isteğin gönderildiğini görürüz. İstekleri sunucu IP’mize göre filtreleyebiliriz, böylece yalnızca web uygulamasının web sunucusuna giden istekleri gösterecektir (yani harici istekleri filtreleyecektir) ve aşağıdaki POST isteğinin gönderildiğini fark edeceğiz:
İsteğe tıklayabilir, İstek sekmesine (istek gövdesini gösterir) tıklayabilir ve ardından ham istek verilerini göstermek için Raw düğmesine tıklayabiliriz. POST istek verisi olarak aşağıdaki verilerin gönderildiğini görüyoruz:
username=admin&password=adminİstek üzerine sağ tıklayıp Kopyala>CURL olarak kopyala’yı seçebiliriz. Bununla birlikte, POST isteklerini manuel olarak oluşturabilmek önemlidir.
Bir POST isteği göndermek için -X POST bayrağını kullanacağız. Ardından, POST verilerimizi eklemek için -d bayrağını kullanabilir .
M1R4CKCK@htb[/htb]$ curl -X POST -d 'username=admin&password=admin' http://<SERVER_IP>:<PORT>/...SNIP...
<em>Type a city name and hit <strong>Enter</strong></em>
...SNIP...
HTML kodunu incelersek, giriş formu kodunu görmeyeceğiz, ancak arama işlevi kodunu göreceğiz, bu da gerçekten kimliğimizin doğrulandığını gösterir.
İpucu: Birçok giriş formu, kimlik doğrulandıktan sonra bizi farklı bir sayfaya yönlendirir (örn. /dashboard.php). Eğer yönlendirmeyi cURL ile takip etmek istiyorsak -L bayrağını kullanabiliriz.
Authenticated Cookies
Kimliğimiz başarıyla doğrulandıysa, tarayıcılarımızın kimlik doğrulamamızı sürdürebilmesi ve sayfayı her ziyaret ettiğimizde giriş yapmamız gerekmemesi için bir cookie almış olmamız gerekir. Kimliği doğrulanmış cookie’mizle birlikte Set-Cookie başlığını içermesi gereken yanıtı görüntülemek için -v veya -i bayraklarını kullanabiliriz:
M1R4CKCK@htb[/htb]$ curl -X POST -d 'username=admin&password=admin'http://<SERVER_IP>:<PORT>/ -i
HTTP/1.1 200 OK
Date:
Server: Apache/2.4.41 (Ubuntu)
Set-Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1; path=/
...SNIP...
<em>Type a city name and hit <strong>Enter</strong></em>
...SNIP...
Kimliği doğrulanmış cookie’miz ile artık her seferinde kimlik bilgilerimizi vermemize gerek kalmadan web uygulaması ile etkileşime geçebilmeliyiz. Bunu test etmek için, yukarıdaki çerezi cURL’de -b bayrağı ile aşağıdaki gibi ayarlayabiliriz:
M1R4CKCK@htb[/htb]$ curl -b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1'http://<SERVER_IP>:<PORT>/
...SNIP...
<em>Type a city name and hit <strong>Enter</strong></em>
...SNIP...
Gördüğümüz gibi, gerçekten de kimliğimiz doğrulandı ve arama işlevine ulaştık. Cookie’yi aşağıdaki gibi bir başlık olarak belirtmek de mümkündür:
Aynı şeyi tarayıcılarımızla da deneyebiliriz. Önce oturumu kapatalım ve sonra giriş sayfasına geri dönelim. Daha sonra [SHIFT+F9] ile devtools içerisindeki Storage sekmesine gidebiliriz. Storage sekmesinde, sol bölmedeki Cookies’e tıklayabilir ve mevcut çerezlerimizi görüntülemek için web sitemizi seçebiliriz. Mevcut çerezlerimiz olabilir veya olmayabilir, ancak oturumu kapattıysak, PHP cookiemizi kimliği doğrulanmamış olmalıdır, bu nedenle arama işlevini değil oturum açma formunu alıyoruz:
Şimdi, daha önce kimliği doğrulanmış cookie’mizi kullanmayı deneyelim ve kimlik bilgilerimizi vermemize gerek kalmadan içeri girip giremeyeceğimizi görelim. Bunu yapmak için, cookie değerini kendi değerimizle değiştirebiliriz. Aksi takdirde, cookienin üzerine sağ tıklayıp Delete All (Tümünü Sil) seçeneğini seçebilir ve yeni bir cookie eklemek için + simgesine tıklayabiliriz. Bundan sonra, = (PHPSESSID)’den önceki kısım olan cookie adını ve ardından = (c1nsa6op7vtk7kdis7bcnbadf1)’den sonraki kısım olan cookie değerini girmemiz gerekir. Ardından, cookie’miz ayarlandıktan sonra sayfayı yenileyebiliriz ve giriş yapmamıza gerek kalmadan, sadece kimliği doğrulanmış bir cookie kullanarak gerçekten kimliğimizin doğrulandığını görürüz:
Gördüğümüz gibi, geçerli bir tanımlama bilgisine sahip olmak birçok web uygulamasında kimlik doğrulaması yapmak için yeterli olabilir. Bu, Cross-Site Scripting gibi bazı web saldırılarının önemli bir parçası olabilir.
JSON Data
Son olarak, City Search fonksiyonu ile etkileşime girdiğimizde hangi isteklerin gönderildiğini görelim. Bunu yapmak için, tarayıcı devtools’unda Network sekmesine gideceğiz ve ardından tüm istekleri temizlemek için çöp kutusu simgesine tıklayacağız. Ardından, hangi isteklerin gönderildiğini görmek için herhangi bir arama sorgusu yapabiliriz:
Gördüğümüz gibi, arama formu search.php’ye aşağıdaki verilerle birlikte bir POST isteği gönderiyor:
{"search":"london"}POST verileri JSON biçiminde görünmektedir, bu nedenle isteğimiz Content-Type başlığını application/json olarak belirtmiş olmalıdır. İsteğe sağ tıklayıp Copy>Copy Request Headers’ı seçerek bunu doğrulayabiliriz:
POST /search.php HTTP/1.1Host: server_ip
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://server_ip/index.php
Content-Type: application/json
Origin: http://server_ip
Content-Length: 19
DNT: 1
Connection: keep-alive
Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1
Gerçekten de Content-Type: application/json başlığımız var. Bu isteği daha önce yaptığımız gibi tekrarlamaya çalışalım, ancak hem cookie hem de content-type başlıklarını ekleyelim ve isteğimizi search.php’ye gönderelim:
M1R4CKCK@htb[/htb]$ curl -X POST -d '{"search":"london"}' -b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' -H 'Content-Type: application/json' http://<SERVER_IP>:<PORT>/search.php["London (UK)"]
Bu, web uygulamalarını bu şekilde test etmek çok daha hızlı olduğundan, web uygulaması değerlendirmeleri veya hata ödül egzersizleri gerçekleştirirken önemli bir beceri olabilir.
Soru : Geçerli bir oturum açma yoluyla bir oturum cookie’si edinin ve ardından ‘/search.php’ adresine bir JSON POST isteği yoluyla bayrağı aramak için cookie’yi cURL ile kullanın
Cevap : Copy>Copy as Curl yaptıktan sonra isteğimizi bu şekilde düzenleyelim. Benim ilk hatam isteği attığımda Content-Type’ı gereksiz görüp silmekti fakat format json olduğu için bunu belirtmeliyiz
CRUD API
Bu bölümde, böyle bir web uygulamasının aynı şeyi gerçekleştirmek için API’leri nasıl kullanabileceğine bakacağız ve API uç noktasıyla doğrudan etkileşime gireceğiz.
API’ler
Çeşitli API türleri vardır. Birçok API bir veritabanıyla etkileşim kurmak için kullanılır, öyle ki API sorgumuzda istenen tabloyu ve istenen satırı belirtebilir ve ardından gereken işlemi gerçekleştirmek için bir HTTP yöntemi kullanabiliriz. Örneğin, örneğimizdeki api.php uç noktası için, veritabanındaki şehir tablosunu güncellemek istiyorsak ve güncelleyeceğimiz satırın bir şehir adı londra ise, URL aşağıdaki gibi görünecektir:
curl -X PUT http://<SERVER_IP>:<PORT>/api.php/city/london ...SNIP...CRUD
Gördüğümüz gibi, bu tür API’ler aracılığıyla üzerinde işlem yapmak istediğimiz tabloyu ve satırı kolayca belirleyebiliyoruz. Daha sonra bu satır üzerinde farklı işlemler gerçekleştirmek için farklı HTTP yöntemleri kullanabiliriz. Genel olarak API’ler talep edilen veritabanı varlığı üzerinde 4 ana işlem gerçekleştirir:
Bu dört işlem temel olarak yaygın olarak bilinen CRUD API’leriyle bağlantılıdır, ancak aynı ilke REST API’lerinde ve diğer birçok API türünde de kullanılır. Elbette, tüm API’ler aynı şekilde çalışmaz ve kullanıcı erişim kontrolü hangi eylemleri gerçekleştirebileceğimizi ve hangi sonuçları görebileceğimizi sınırlayacaktır.
Read
Bir API ile etkileşime girerken yapacağımız ilk şey veri okumaktır. Daha önce de belirtildiği gibi, API’den sonra tablo adını (örn. /city) ve ardından arama terimimizi (örn. /london) aşağıdaki gibi belirtebiliriz:
M1R4CKCK@htb[/htb]$ curl http://<SERVER_IP>:<PORT>/api.php/city/london[{"city_name":"London","country_name":"(UK)"}]
Sonucun bir JSON dizesi olarak gönderildiğini görüyoruz. JSON formatında düzgün bir şekilde biçimlendirmek için, çıktıyı düzgün bir şekilde biçimlendirecek olan jq yardımcı programına aktarabiliriz. Gereksiz cURL çıktılarını da -s ile aşağıdaki gibi susturacağız:
M1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/london | jq[
{
"city_name": "London",
"country_name": "(UK)"
}
]
Gördüğümüz gibi, çıktıyı güzel bir şekilde biçimlendirilmiş bir çıktı olarak aldık. Ayrıca bir arama terimi sağlayabilir ve eşleşen tüm sonuçları alabiliriz:
M1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/le | jq[
{
"city_name": "Leeds",
"country_name": "(UK)"
},
{
"city_name": "Dudley",
"country_name": "(UK)"
},
{
"city_name": "Leicester",
"country_name": "(UK)"
},
...SNIP...
]
Son olarak, tablodaki tüm girdileri almak için boş bir dize geçebiliriz:
M1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/ | jq[
{
"city_name": "London",
"country_name": "(UK)"
},
{
"city_name": "Birmingham",
"country_name": "(UK)"
},
{
"city_name": "Leeds",
"country_name": "(UK)"
},
...SNIP...
]
Create
Yeni bir girdi eklemek için, önceki bölümde gerçekleştirdiğimize oldukça benzeyen bir HTTP POST isteği kullanabiliriz. JSON verilerimizi basitçe POST edebiliriz ve tabloya eklenecektir. Bu API JSON verilerini kullandığından, Content-Type başlığını da aşağıdaki gibi JSON olarak ayarlayacağız:
M1R4CKCK@htb[/htb]$ curl -X POST http://<SERVER_IP>:<PORT>/api.php/city/-d '{"city_name":"HTB_City", "country_name":"HTB"}'
-H 'Content-Type: application/json'
Şimdi, başarıyla eklenip eklenmediğini görmek için eklediğimiz şehrin (HTB_City) içeriğini okuyabiliriz:
M1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/HTB_City | jq[
{
"city_name": "HTB_City",
"country_name": "HTB"
}
]
Gördüğümüz gibi, daha önce var olmayan yeni bir şehir yaratıldı.
Update
Şimdiye kadar kullanmadığımız diğer iki HTTP yöntemini tartışmaya başlayalım: PUT ve DELETE. Bölümün başında belirtildiği gibi, PUT API girdilerini güncellemek ve ayrıntılarını değiştirmek için kullanılırken, DELETE belirli bir varlığı kaldırmak için kullanılır.
Not: API girdilerini güncellemek için PUT yerine HTTP PATCH yöntemi de kullanılabilir. Kesin olmak gerekirse, PATCH bir girişi kısmen güncellemek için kullanılırken (yalnızca bazı verilerini değiştirmek “örneğin yalnızca city_name”), PUT tüm girişi güncellemek için kullanılır. Sunucu tarafından hangisinin kabul edildiğini görmek için HTTP OPTIONS yöntemini de kullanabilir ve ardından buna göre uygun yöntemi kullanabiliriz. Bu bölümde, kullanımları oldukça benzer olsa da PUT yöntemine odaklanacağız.
Bu durumda PUT kullanmak POST’a oldukça benzerdir, tek fark URL’de düzenlemek istediğimiz varlığın adını belirtmek zorunda olmamızdır, aksi takdirde API hangi varlığı düzenleyeceğini bilemez. Dolayısıyla, tek yapmamız gereken URL’de şehir adını belirtmek, istek yöntemini PUT olarak değiştirmek ve POST ile yaptığımız gibi JSON verilerini aşağıdaki gibi sağlamaktır:
M1R4CKCK@htb[/htb]$ curl -X PUT http://<SERVER_IP>:<PORT>/api.php/city/london -d '{"city_name":"New_HTB_City", "country_name":"HTB"}' -H 'Content-Type: application/json'Yukarıdaki örnekte ilk olarak şehrimiz olarak /city/london belirttiğimizi ve istek verisinde “city_name”: “New_HTB_City” içeren bir JSON dizesi ilettiğimizi görüyoruz. Dolayısıyla, londra şehri artık mevcut olmamalı ve New_HTB_City adında yeni bir şehir mevcut olmalıdır. Doğrulamak için ikisini de okumayı deneyelim:
M1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/london | jqM1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_City| jq
[
{
"city_name": "New_HTB_City",
"country_name": "HTB"
}
]
Gerçekten de, eski şehir adını yeni şehirle başarıyla değiştirdik.
Not: Bazı API’lerde, Update işlemi yeni girişler oluşturmak için de kullanılabilir. Temel olarak, verilerimizi göndeririz ve eğer mevcut değilse, onu oluşturur. Örneğin, yukarıdaki örnekte, londra şehrine sahip bir giriş mevcut olmasa bile, ilettiğimiz ayrıntılarla yeni bir giriş oluşturacaktır. Ancak bizim örneğimizde durum böyle değildir.
DELETE
Son olarak, bir şehri okumak kadar kolay olan bir şehri silmeyi deneyelim. API için sadece şehir adını belirtiriz ve HTTP DELETE yöntemini kullanırız ve aşağıdaki gibi girişi siler:
M1R4CKCK@htb[/htb]$ curl -X DELETE http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_CityM1R4CKCK@htb[/htb]$ curl -s http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_City| jq
[]
Gördüğümüz gibi, New_HTB_City’yi sildikten sonra, okumayı denediğimizde boş bir dizi elde ediyoruz, yani artık mevcut değil.
Bu sayede, cURL aracılığıyla 4 CRUD işleminin tamamını gerçekleştirebiliyoruz. Gerçek bir web uygulamasında, bu tür eylemlere tüm kullanıcılar için izin verilmeyebilir veya herhangi birinin herhangi bir girişi değiştirebilmesi veya silebilmesi bir güvenlik açığı olarak kabul edilir. Her kullanıcı neleri okuyabileceği veya yazabileceği konusunda belirli ayrıcalıklara sahip olacaktır; burada yazma, veri ekleme, değiştirme veya silme anlamına gelir.
Soru : İlk olarak, herhangi bir şehrin adını ‘flag’ olarak güncellemeyi deneyin. Ardından, herhangi bir şehri silin. Bunu yaptıktan sonra, bayrağı almak için ‘bayrak’ adlı bir şehri arayın.
Cevap :
1- Öncelikle bir şehrin adını flag ile değiştirdik . (Güncelledik)
2- Ardından herhangi bir şehiri sildik . (DELETE)
3- Son olarak flag isimli şehrimizi okuduk . (Get)
Okuduğunuz için teşekkürler.