Korunuyor musunuz?
Tags: modsec, waf, server, security
Published: 2023-03-24 12:15:02

Böyle bir başlık ile aklınızda farklı bir çağrışım yaratmadan konunun amacına hızlı bir giriş yapmak istiyorum.

Sadece web sitenizi veya uygulamanızı bir sunucuya deploy etmek, anahtarları kapının üzerinde bırakmaktan farklı bir eylem değildir. Sunucu üzerinde; gerek servislerde, gerek yazılım dosyalarınızda, gerekse ağ yapılandırmanızla gerekli güvenlik önlemleri almanız günümüzün en temel sunucu yönetimi işlemleri arasında yer almaktadır.

Hala SSH portunu 22 bırakmak, RDP portunu 3389 bırakmak veya bu servislere IP bazlı kısıtlamamak ya da en azından bir brute-force atak durumunda engelleme yapmamak gibi hataya düşenler var. 

Bu yazı içerisinde sunucu tarafında alınabilecek güvenlik önlemlerinden sadece birini ve bence en önemlisini; HTTP & HTTPS trafiğini korumanın temel adımlarına değineceğim. 

## ModSecurity nedir?

ModSecurity, açık kaynak kodlu bir WAF (web application firewall) yazılımıdır. Apache için üretilmiş olup, nginx, litespeed ve IIS gibi diğer web servisleri için de desteği bulunmaktadır. 

ModSecurity, HTTP trafiğini detaylı bir şekilde dinleyerek, yaşam döngüsü içerisinde gelen istekleri kabul edip etmeyeceğinizi ve istekleri manipüle edebilmeniz bir konfigürasyon sağlar. 

ModSecurity, günümüzde milyonlarca sunucuda bulunuyor. Üzerine yazılan kurallar hemen hemen her konfigürasyona ait sunucuda aynı şekilde çalışıyor. ModSecurity için hazırlanmış, ücretli ve open-source birçok kural seti bulunmaktadır.

## ModSecurity ile neler yapabiliriz?

Başlıca olarak şunları yapabiliriz;

- User-Agent'a göre engelleme,
- IP adresi veya belirli subnete göre engelleme,
- GeoLookup bazlı engelleme,
- Belirli süre içerisinde gelen istek sayısına göre engelleme,
- Referer bilgisine göre engelleme,
- XSS gibi bilinen açıkları engelleme,
- Wordpress gibi bilinen open-source yazılımların veya kendi yazılımlarınızın açıklarını engelleme,

### ModSec ile User-Agent Engelleme

Web sitenize veya uygulamanıza gönderilen istekleri incelediğinizde tanımadığınız veya güvenli bulmadığınız istekleri analiz ederek, aşağıdaki kuralda olduğu gibi engelleme yapabilirsiniz.

```
SecRule HTTP_User-Agent "zgrab" "deny,status:403,log,id:9000001,msg:'Bad Bot'"
```

Engelleme sonrasında isteklere 403 kodu ile yanıt verilmiş olacaktır.

_204.48.26.63 - - [24/Mar/2023:14:14:07 +0300] "GET /ab2g HTTP/1.1" **403** 1249 "-" "**Mozilla/5.0 zgrab/0.x**"_

Eklenen kurallarda HTTP_User-Agent sonrasındaki parametreye girilen değer User-Agent bilgisi içerisinde aranır ve büyük küçük harf duyarlılığı vardır.

Bilinen tarayıcıların eski versiyonlarını da aşağıdaki gibi kural ekleyerek engellemek istenmeyen trafiği azaltmaya faydalı olacaktır.

```
SecRule HTTP_User-Agent "Firefox/10.0" "deny,status:403,log,id:900002,msg:'Bad Bot'"
SecRule HTTP_User-Agent "Firefox/12.0" "deny,status:403,log,id:900003,msg:'Bad Bot'"
SecRule HTTP_User-Agent "Firefox/13.0" "deny,status:403,log,id:900004,msg:'Bad Bot'"
SecRule HTTP_User-Agent "Firefox/14.0" "deny,status:403,log,id:900005,msg:'Bad Bot'"
```

Tarayıcılar günümüzde otomatik olarak güncellendikleri için User-Agent değerleri de güncellenmektedir. Genellikle, eski Firefox, Chrome, Opera ve diğer tarayıcı sürümlerini bot yazılımlar kullanmaktadır.

### ModSec ile Boş User-Agent Engelleme

Bilinen bütün tarayıcılar mutlaka User-Agent bilgisini iletir. Eğer User-Agent boş olarak istek atılıyorsa, bu zararlı bir botun gönderdiği istek olabilir. Dolayısıyla, bunu engellemekte de fayda var.

```
SecRule &REQUEST_HEADERS:User-Agent "@eq 0" "deny,status:403,log,id:900006,msg:'Empty User-Agent'"
SecRule REQUEST_HEADERS:User-Agent "^$" "deny,status:403,log,id:900007,msg:'Empty User-Agent'"
```

### ModSec ile Sahte Googlebot Engelleme

Google, websitelerini indekslemek için gönderdiği botların IP adreslerini [burada](https://www.gstatic.com/ipranges/goog.json) JSON formatında güncel olarak paylaşıyor (referans; [Googlebot'u ve diğer Google tarayıcılarını doğrulama](https://developers.google.com/search/docs/crawling-indexing/verifying-googlebot?hl=tr)). 

Gelen isteklerin gerçekten Google'a ait olup olmadığını en doğru şekilde kontrol edebilmek için bu listeyi kullanabiliriz. Bu IP adreslerini googlebot-ips.txt isminde bir dosya oluşturup içerisine yazarsak ve bu IP adresleri haricinde Google olarak istek gönderen botları engellersek, sahte botların website içeriğini çalmasına veya load oluşturmasına müsade etmemiş oluruz.
 
**Kurallar;**

```
SecRule REMOTE_ADDR "@ipMatchFromFile googlebot-ips.txt" "allow,log,id:999998,ctl:ruleRemoveById=999999,msg:'Real Googlebot'"

SecRule HTTP_User-Agent "Google" "deny,status:403,log,id:999999,msg:'Bad Googlebot'"
```

**Google IP Adresleri Listesi;**

IPv4 ve IPv6 IP adreslerinin listesini bir txt dosyası içerisine aldım. [https://www.grkn.co/repo/googlebot-ips.txt](https://www.grkn.co/repo/googlebot-ips.txt) adresinden **24 Mart 2023 14:39** tarihli bu listeye ulaşabilirsiniz. 

### ModSec ile IP Adresine Göre Engelleme

Kendimize bir karaliste oluşturabiliriz. Belirli IP adresleri ve subnetlerden gelen istekleri, sunucu içerisindeki tüm siteler için engelleyebiliriz.

```
SecRule REMOTE_ADDR "@ipMatchFromFile blacklist-ips.txt" "deny,status:403,log,id:999997,msg:'Bad Guys'"
```

blacklist-ips.txt dosyası aşağıdaki formatta olmalı. 

```
192.168.1.0/24
10.0.0.1
127.0.0.1
```

Sadece belirli bir IP adresini engellemek için de kural oluşturabiliriz. 

```
SecRule REMOTE_ADDR "@ipMatch 192.168.1.101" "deny,status:403,log,id:999996,msg:'Bad Guy'"
```

Ancak, ModSec üzerinde spesifik bir IP adresini engellemeyi uygun bulmuyorum. 

Bunu bir .htaccess dosyası veya nginx.conf dosyası ile de yapabiliriz. IPTables veya Windows Firewall gibi yazılım üzerinden de engelleyebiliriz. ModSec kural dosyasını tek bir IP adresi için şişirmeyi pek tavsiye etmiyorum. 

### Dipnot

- Kuralları modsec2.user.conf dosyası içerisine yazmalı ve kural ekleme sonrasında web servisinizi resetlemelisiniz.
- googlebot-ips.txt ve blacklist-ips.txt dosyaları modsec2.user.conf dosyanız ile aynı dizinde olmalıdır. 
- Listeye tek IP eklemek için /32 yazarsanız web servisiniz hata verir, o yüzden 192.168.1.101/32 yerine 192.168.1.101 yazmalısınız. 
- Bu yazıyı ilerleyen zamanlarda tekrar güncellemeyi planlıyorum.