
3 new exploits WinFTP Server 2.0.2 - (PASV) Remote Denial of Service WinFTP Server 2.0.2 - 'PASV' Remote Denial of Service WinFTP Server 2.3.0 - (NLST) Denial of Service WinFTP Server 2.3.0 - 'NLST' Denial of Service vxFtpSrv 2.0.3 - CWD command Remote Buffer Overflow (PoC) vxFtpSrv 2.0.3 - 'CWD' Remote Buffer Overflow (PoC) OpenSSH < 7.4 - 'UsePrivilegeSeparation Disabled' Forwarded Unix Domain Sockets Privilege Escalation X7 Chat 2.0.5 - lib/message.php preg_replace() PHP Code Execution (Metasploit) X7 Chat 2.0.5 - 'message.php' PHP Code Execution (Metasploit) OpenSSH < 7.4 - agent Protocol Arbitrary Library Loading X7 Chat 2.0 - (help_file) Remote Command Execution X7 Chat 2.0 - 'help_file' Parameter Remote Command Execution Ultimate WebBoard 3.00 - (Category) SQL Injection PromoteWeb MySQL - 'go.php id' SQL Injection 212Cafe Board 0.07 - (view.php qID) SQL Injection Ultimate WebBoard 3.00 - 'Category' Parameter SQL Injection PromoteWeb MySQL - 'id' Parameter SQL Injection 212Cafe Board 0.07 - 'qID' Parameter SQL Injection The Gemini Portal - 'lang' Remote File Inclusion RPG.Board 0.0.8Beta2 - (showtopic) SQL Injection ASPapp KnowledgeBase - 'catid' SQL Injection The Gemini Portal 4.7 - 'lang' Parameter Remote File Inclusion RPG.Board 0.0.8Beta2 - 'showtopic' Parameter SQL Injection ASPapp KnowledgeBase - 'catid' Parameter SQL Injection X7 Chat 2.0.1A1 - (mini.php help_file) Local File Inclusion X7 Chat 2.0.1A1 - 'mini.php' Local File Inclusion CoAST 0.95 - (sections_file) Remote File Inclusion Real Estate Manager - 'cat_id' SQL Injection LnBlog 0.9.0 - (plugin) Local File Inclusion PlugSpace 0.1 - (index.php navi) Local File Inclusion MyCard 1.0.2 - (gallery.php id) SQL Injection PowerPortal 2.0.13 - 'path' Local Directory Traversal PHP-Lance 1.52 - (show.php catid) SQL Injection Yoxel 1.23beta - (itpm_estimate.php a) Remote Code Execution CoAST 0.95 - 'sections_file' Parameter Remote File Inclusion Real Estate Manager 1.01 - 'cat_id' Parameter SQL Injection LnBlog 0.9.0 - 'plugin' Parameter Local File Inclusion PlugSpace 0.1 - 'navi' Parameter Local File Inclusion MyCard 1.0.2 - 'id' Parameter SQL Injection PowerPortal 2.0.13 - 'path' Parameter Local Directory Traversal PHP-Lance 1.52 - 'catid' Parameter SQL Injection Yoxel 1.23beta - 'itpm_estimate.php' Remote Code Execution ZEELYRICS 2.0 - (bannerclick.php adid) SQL Injection ZEELYRICS 2.0 - 'bannerclick.php' SQL Injection Pro Chat Rooms 3.0.3 - (guid) SQL Injection Pilot Group eTraining - 'news_read.php id' SQL Injection BbZL.php 0.92 - (lien_2) Local Directory Traversal Pro Chat Rooms 3.0.3 - SQL Injection Pilot Group eTraining - 'news_read.php' SQL Injection BbZL.php 0.92 - 'lien_2' Parameter Local Directory Traversal Arcadem Pro - 'articlecat' SQL Injection Arcadem Pro - 'articlecat' Parameter SQL Injection ArabCMS - 'rss.php rss' Local File Inclusion FAQ Management Script - 'catid' SQL Injection ArabCMS - 'rss.php' Local File Inclusion FAQ Management Script - 'catid' Parameter SQL Injection BookMarks Favourites Script - 'view_group.php id' SQL Injection BookMarks Favourites Script - 'id' Parameter SQL Injection BMForum 5.6 - (tagname) SQL Injection BMForum 5.6 - 'tagname' Parameter SQL Injection Crux Gallery 1.32 - (index.php theme) Local File Inclusion phpScheduleIt 1.2.10 - (reserve.php) Remote Code Execution RPortal 1.1 - (file_op) Remote File Inclusion Crux Gallery 1.32 - 'theme' Parameter Local File Inclusion phpScheduleIt 1.2.10 - 'reserve.php' Remote Code Execution RPortal 1.1 - 'file_op' Parameter Remote File Inclusion Link Trader - 'ratelink.php lnkid' SQL Injection Link Trader - 'lnkid' Parameter SQL Injection OLIB 7 WebView 2.5.1.1 - (infile) Local File Inclusion OpenX 2.6 - (ac.php bannerid) Blind SQL Injection OLIB 7 WebView 2.5.1.1 - 'infile' Parameter Local File Inclusion OpenX 2.6 - 'bannerid' Parameter Blind SQL Injection X7 Chat 2.0.5 - (Authentication Bypass) SQL Injection X7 Chat 2.0.5 - Authentication Bypass Arcadem Pro 2.8 - (article) Blind SQL Injection Arcadem Pro 2.8 - 'article' Parameter Blind SQL Injection Link Trader - (lnkid) SQL Injection phpScheduleIt PHP - reserve.php start_date Parameter Arbitrary Code Injection (Metasploit) phpScheduleIt 1.2.10 - 'reserve.php' Arbitrary Code Injection (Metasploit) PowerPortal 1.1/1.3 - modules.php Traversal Arbitrary Directory Listing PowerPortal 1.1/1.3 - 'modules.php' Traversal Arbitrary Directory Listing Atomic Photo Album 0.x/1.0 - Apa_PHPInclude.INC.php Remote File Inclusion Atomic Photo Album 0.x/1.0 - 'Apa_PHPInclude.INC.php' Remote File Inclusion BMForum 3.0 - topic.php Multiple Parameter Cross-Site Scripting BMForum 3.0 - forums.php Multiple Parameter Cross-Site Scripting BMForum 3.0 - post.php forumid Parameter Cross-Site Scripting BMForum 3.0 - announcesys.php forumid Parameter Cross-Site Scripting BMForum 3.0 - 'topic.php' Cross-Site Scripting BMForum 3.0 - 'forums.php' Cross-Site Scripting BMForum 3.0 - 'post.php' Cross-Site Scripting BMForum 3.0 - 'announcesys.php' Cross-Site Scripting PowerPortal 1.1/1.3 - 'index.php' search Parameter Cross-Site Scripting PowerPortal 1.1/1.3 - search.php search Parameter Cross-Site Scripting PowerPortal 1.1/1.3 - 'index.php' Cross-Site Scripting PowerPortal 1.1/1.3 - 'search.php' Cross-Site Scripting X7 Chat 2.0.4 - sources/frame.php room Parameter Cross-Site Scripting X7 Chat 2.0.4 - upgradev1.php INSTALL_X7CHATVERSION Parameter Cross-Site Scripting X7 Chat 2.0.4 - 'frame.php' Cross-Site Scripting X7 Chat 2.0.4 - 'upgradev1.php' Cross-Site Scripting BMForum 5.6 - 'index.php' outpused Parameter Cross-Site Scripting BMForum 5.6 - newtem/footer/bsd01footer.php Multiple Parameter Cross-Site Scripting BMForum 5.6 - newtem/header/bsd01header.php Multiple Parameter Cross-Site Scripting BMForum 5.6 - 'index.php' Cross-Site Scripting BMForum 5.6 - 'bsd01footer.php' Cross-Site Scripting BMForum 5.6 - 'bsd01header.php' Cross-Site Scripting Pilot Group eTraining - courses_login.php cat_id Parameter Cross-Site Scripting Pilot Group eTraining - news_read.php id Parameter Cross-Site Scripting Pilot Group eTraining - lessons_login.php Multiple Parameter Cross-Site Scripting Pilot Group eTraining - 'courses_login.php' Cross-Site Scripting Pilot Group eTraining - 'news_read.php' Cross-Site Scripting Pilot Group eTraining - 'lessons_login.php' Cross-Site Scripting OpenX - /www/admin/plugin-index.php parent Parameter Cross-Site Scripting OpenX 2.8.10 - 'plugin-index.php' Cross-Site Scripting Apache mod_session_crypto - Padding Oracle
154 lines
7.2 KiB
Text
Executable file
154 lines
7.2 KiB
Text
Executable file
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=926
|
|
|
|
mach ports are really struct ipc_port_t's in the kernel; this is a reference-counted object,
|
|
ip_reference and ip_release atomically increment and decrement the 32 bit io_references field.
|
|
|
|
Unlike OSObjects, ip_reference will allow the reference count to overflow, however it is still 32-bits
|
|
so without either a lot of physical memory (which you don't have on mobile or most desktops) or a real reference leak
|
|
this isn't that interesting.
|
|
|
|
** MIG and mach message rights ownership **
|
|
|
|
ipc_kobject_server in ipc_kobject.c is the main dispatch routine for the kernel MIG endpoints. When userspace sends a
|
|
message the kernel will copy in the message body and also copy in all the message rights; see for example
|
|
ipc_right_copyin in ipc_right.c. This means that by the time we reach the actual callout to the MIG handler any port rights
|
|
contained in a request have had their reference count increased by one.
|
|
|
|
After the callout we reach the following code (still in ipc_kobject_server):
|
|
|
|
if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
|
|
// The server function is responsible for the contents
|
|
// of the message. The reply port right is moved
|
|
// to the reply message, and we have deallocated
|
|
// the destination port right, so we just need
|
|
// to free the kmsg.
|
|
ipc_kmsg_free(request);
|
|
} else {
|
|
// The message contents of the request are intact.
|
|
// Destroy everthing except the reply port right,
|
|
// which is needed in the reply message.
|
|
request->ikm_header->msgh_local_port = MACH_PORT_NULL;
|
|
ipc_kmsg_destroy(request);
|
|
}
|
|
|
|
If the MIG callout returns success, then it means that the method took ownership of *all* of the rights contained in the message.
|
|
If the MIG callout returns a failure code then the means the method took ownership of *none* of the rights contained in the message.
|
|
|
|
ipc_kmsg_free will only destroy the message header, so if the message had any other port rights then their reference counts won't be
|
|
decremented. ipc_kmsg_destroy on the other hand will decrement the reference counts for all the port rights in the message, even those
|
|
in port descriptors.
|
|
|
|
If we can find a MIG method which returns KERN_SUCCESS but doesn't in fact take ownership of any mach ports its passed (by for example
|
|
storing them and dropping the ref later, or using them then immediately dropping the ref or passing them to another method which takes
|
|
ownership) then this can lead to us being able to leak references.
|
|
|
|
** indirect MIG methods **
|
|
|
|
Here's the MIG request structure generated for io_service_add_notification_ool_64:
|
|
|
|
typedef struct {
|
|
mach_msg_header_t Head;
|
|
// start of the kernel processed data
|
|
mach_msg_body_t msgh_body;
|
|
mach_msg_ool_descriptor_t matching;
|
|
mach_msg_port_descriptor_t wake_port;
|
|
// end of the kernel processed data
|
|
NDR_record_t NDR;
|
|
mach_msg_type_number_t notification_typeOffset; // MiG doesn't use it
|
|
mach_msg_type_number_t notification_typeCnt;
|
|
char notification_type[128];
|
|
mach_msg_type_number_t matchingCnt;
|
|
mach_msg_type_number_t referenceCnt;
|
|
io_user_reference_t reference[8];
|
|
mach_msg_trailer_t trailer;
|
|
} Request __attribute__((unused));
|
|
|
|
|
|
This is an interesting method as its implementation actually calls another MIG handler:
|
|
|
|
|
|
static kern_return_t internal_io_service_add_notification_ool(
|
|
...
|
|
kr = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) matching );
|
|
data = CAST_DOWN(vm_offset_t, map_data);
|
|
|
|
if( KERN_SUCCESS == kr) {
|
|
// must return success after vm_map_copyout() succeeds
|
|
// and mig will copy out objects on success
|
|
*notification = 0;
|
|
*result = internal_io_service_add_notification( master_port, notification_type,
|
|
(char *) data, matchingCnt, wake_port, reference, referenceSize, client64, notification );
|
|
vm_deallocate( kernel_map, data, matchingCnt );
|
|
}
|
|
|
|
return( kr );
|
|
}
|
|
|
|
|
|
and internal_io_service_add_notification does this:
|
|
|
|
|
|
static kern_return_t internal_io_service_add_notification(
|
|
...
|
|
if( master_port != master_device_port)
|
|
return( kIOReturnNotPrivileged);
|
|
|
|
do {
|
|
err = kIOReturnNoResources;
|
|
|
|
if( !(sym = OSSymbol::withCString( notification_type )))
|
|
err = kIOReturnNoResources;
|
|
|
|
if (matching_size)
|
|
{
|
|
dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching, matching_size));
|
|
}
|
|
else
|
|
{
|
|
dict = OSDynamicCast(OSDictionary, OSUnserializeXML(matching));
|
|
}
|
|
|
|
if (!dict) {
|
|
err = kIOReturnBadArgument;
|
|
continue;
|
|
}
|
|
...
|
|
} while( false );
|
|
|
|
return( err );
|
|
|
|
|
|
This inner function has many failure cases (wrong kernel port, invalid serialized data) which we can easily trigger and these error paths lead
|
|
to this inner function not taking ownership of the wake_port argument. However, MIG will only see the return value of the outer internal_io_service_add_notification_ool
|
|
which will always return success if we pass a valid ool memory descriptor. This violates ipc_kobject_server's ownership model where success means ownership
|
|
was taken of all rights, not just some.
|
|
|
|
What this leads to is actually quite a nice primitive for constructing an ipc_port_t reference count overflow without leaking any memory.
|
|
|
|
If we call io_service_add_notification_ool with a valid ool descriptor, but fill it with data that causes OSUnserializeXML to return an error then
|
|
we can get that memory freed (via the vm_deallocate call above) but the reference on the wake port will be leaked since ipc_kmsg_free will be called, not
|
|
ipc_kmsg_destroy.
|
|
|
|
If we send this request 0xffffffff times we can cause a ipc_port_t's io_references field to overflow to 0; the next time it's used the ref will go 0 -> 1 -> 0
|
|
and the object will be free'd but we'll still have a dangling pointer in our process's ports table.
|
|
|
|
As well as being a regular kernel UaF this also gives us the opportunity to do all kinds of fun mach port related logic attacks, eg getting send rights to
|
|
other task's task ports via our dangling ipc_port_t pointer.
|
|
|
|
** practicality **
|
|
|
|
On my 4 year old dual core MBA 5,2 running with two threads this PoC takes around 8 hours after which you should see a kernel panic indicative of a UaF.
|
|
Note that there are no resources leaks involved here so you can run it even on very constrained systems like an iPhone and it will work fine,
|
|
albeit a bit slowly :)
|
|
|
|
This code is reachable from all sandboxed environments.
|
|
|
|
** fixes **
|
|
|
|
One approach to fixing this issue would be to do something similar to OSObjects which use a saturating reference count and leak the object if the reference count saturates
|
|
|
|
I fear there are a great number of similar issues so just fixing this once instance may not be enough.
|
|
|
|
|
|
Proof of Concept:
|
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/40955.zip
|