PLAIN stupid czyli jak zostałem spamerem

Dzisiaj będzie o głupim błędzie w konfiguracji Exima, który wynikł z bezrefleksyjnego kopiowania i wklejania opublikowanych w Internecie przykładowych konfiguracji.

Ze zdziwieniem przeczytałem maila z serwerowni informującego, że z mojego serwera jest wysyłany spam. Dołączony w załączniku mail wyglądał na wysłany z mojego serwera, a w logach Exima znalazłem informację o wysłaniu inkryminowanej wiadomości, więc o pomyłce serwerowni nie było mowy.

2012-06-22 09:34:16 1ShyNj-0000KH-Cx <= harun@digit0.com H=server177288-1.santrex.net [37.59.45.10] P=esmtpa A=plain_pgsql:sales S=3593 id=73D566338398i-49A3A971B01x025-29B991E@PHRSBS
2012-06-22 09:34:18 1ShyNj-0000KH-Cx => altairhosttest@hotmail.com R=dnslookup T=remote_smtp H=mx2.hotmail.com [65.54.188.94]
2012-06-22 09:34:18 1ShyNj-0000KH-Cx Completed

Z powyższego wycinka logów wynika, że spamer z adresu 37.59.45.10 z powodzeniem autoryzował się jako użytkownik sales przy użyciu autoryzacji plain_pgsql. Stosowna regułka wyglądała tak:

plain_pgsql:
   driver = plaintext
   public_name = PLAIN
   server_condition = ${if eq{$auth3}{${lookup pgsql{SELECT password FROM exim_virtual_users WHERE login = '${quote_pgsql:$auth2}'}}}{yes}{no}}
   server_set_id = $auth2
   server_prompts = :

Powyższy mechanizm wyszukuje w bazie dane użytkownika o podanym loginie ($auth2) i uzyskane w ten sposób hasło porównuje z hasłem podanym przez użytkownika ($auth3). Gdzie tkwi problem? Otóż powyższy mechanizm działa świetnie dla użytkowników, którzy istnieją w bazie. Jeśli jednak sprytny spamer poda nieistniejącego użytkownika i puste hasło to autoryzacja przebiega pomyślnie! Dzieje się tak ponieważ dla nieistniejącego użytkownika zwracane jest puste hasło, a puste hasło = puste hasło.

Dokładnie ten przypadek został opisany w dokumentacji Exima, więc sobie ku pamięci i wszystkim zainteresowanym powtarzam: RTFM!

Dla porządku podaję jeszcze poprawną wersję regułki autoryzującej:

plain_pgsql:
   driver = plaintext
   public_name = PLAIN
   server_condition = ${if and{{!eq{$auth2}{}} {!eq{$auth3}{}} {eq{$auth3}{${lookup pgsql{SELECT password FROM exim_virtual_users WHERE login = '${quote_pgsql:$auth2}'}}}}} {yes}{no}}
   server_set_id = $auth2
   server_prompts = :