
1979 changes to exploits/shellcodes Couchdb 1.5.0 - 'uuids' Denial of Service Apache CouchDB 1.5.0 - 'uuids' Denial of Service Beyond Remote 2.2.5.3 - Denial of Service (PoC) udisks2 2.8.0 - Denial of Service (PoC) Termite 3.4 - Denial of Service (PoC) SoftX FTP Client 3.3 - Denial of Service (PoC) Silverstripe 2.3.5 - Cross-Site Request Forgery / Open redirection SilverStripe CMS 2.3.5 - Cross-Site Request Forgery / Open Redirection Silverstripe CMS 3.0.2 - Multiple Vulnerabilities SilverStripe CMS 3.0.2 - Multiple Vulnerabilities Silverstripe CMS 2.4 - File Renaming Security Bypass SilverStripe CMS 2.4 - File Renaming Security Bypass Silverstripe CMS 2.4.5 - Multiple Cross-Site Scripting Vulnerabilities SilverStripe CMS 2.4.5 - Multiple Cross-Site Scripting Vulnerabilities Silverstripe CMS 2.4.7 - 'install.php' PHP Code Injection SilverStripe CMS 2.4.7 - 'install.php' PHP Code Injection Silverstripe Pixlr Image Editor - 'upload.php' Arbitrary File Upload SilverStripe CMS Pixlr Image Editor - 'upload.php' Arbitrary File Upload Silverstripe CMS 2.4.x - 'BackURL' Open Redirection SilverStripe CMS 2.4.x - 'BackURL' Open Redirection Silverstripe CMS - 'MemberLoginForm.php' Information Disclosure SilverStripe CMS - 'MemberLoginForm.php' Information Disclosure Silverstripe CMS - Multiple HTML Injection Vulnerabilities SilverStripe CMS - Multiple HTML Injection Vulnerabilities Apache CouchDB 1.7.0 and 2.x before 2.1.1 - Remote Privilege Escalation Apache CouchDB 1.7.0 / 2.x < 2.1.1 - Remote Privilege Escalation Monstra CMS before 3.0.4 - Cross-Site Scripting Monstra CMS < 3.0.4 - Cross-Site Scripting (2) Monstra CMS < 3.0.4 - Cross-Site Scripting Monstra CMS < 3.0.4 - Cross-Site Scripting (1) Navigate CMS 2.8 - Cross-Site Scripting Collectric CMU 1.0 - 'lang' SQL injection Joomla! Component CW Article Attachments 1.0.6 - 'id' SQL Injection LG SuperSign EZ CMS 2.5 - Remote Code Execution MyBB Visual Editor 1.8.18 - Cross-Site Scripting Joomla! Component AMGallery 1.2.3 - 'filter_category_id' SQL Injection Joomla! Component Micro Deal Factory 2.4.0 - 'id' SQL Injection RICOH Aficio MP 301 Printer - Cross-Site Scripting Joomla! Component Auction Factory 4.5.5 - 'filter_order' SQL Injection RICOH MP C6003 Printer - Cross-Site Scripting Linux/ARM - Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) Shellcode (28 Bytes) Linux/ARM - sigaction() Based Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) Shellcode (52 Bytes)
164 lines
No EOL
7.7 KiB
Text
164 lines
No EOL
7.7 KiB
Text
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=780
|
|
|
|
Several functions in the GPU command buffer service interact with the GPU
|
|
mailbox manager (gpu/command_buffer/service/mailbox_manager_impl.cc), passing a reference to shared memory as the mailbox argument.
|
|
|
|
MailboxManagerImpl does not expect this mailbox argument to be malleable in this way, and it is in several places copied and passed to various stl functions, resulting in unexpected behaviour from double-reads when an attacker modifies the mailbox name mid function.
|
|
|
|
The attached POC uses the GPU command 'ProduceTextureDirectCHROMIUMImmediate' to trigger a use-after-free but other commands that interact with the mailbox manager should also be vulnerable in a similar way.
|
|
|
|
error::Error GLES2DecoderImpl::HandleProduceTextureDirectCHROMIUMImmediate(
|
|
uint32_t immediate_data_size,
|
|
const void* cmd_data) {
|
|
const gles2::cmds::ProduceTextureDirectCHROMIUMImmediate& c =
|
|
*static_cast<const gles2::cmds::ProduceTextureDirectCHROMIUMImmediate*>(
|
|
cmd_data);
|
|
(void)c;
|
|
GLuint texture = c.texture;
|
|
GLenum target = static_cast<GLenum>(c.target);
|
|
uint32_t data_size;
|
|
if (!ComputeDataSize(1, sizeof(GLbyte), 64, &data_size)) {
|
|
return error::kOutOfBounds;
|
|
}
|
|
if (data_size > immediate_data_size) {
|
|
return error::kOutOfBounds;
|
|
}
|
|
|
|
// ** mailbox is a pointer into our shared memory buffer **
|
|
const GLbyte* mailbox =
|
|
GetImmediateDataAs<const GLbyte*>(c, data_size, immediate_data_size);
|
|
if (!validators_->texture_bind_target.IsValid(target)) {
|
|
LOCAL_SET_GL_ERROR_INVALID_ENUM("glProduceTextureDirectCHROMIUM", target,
|
|
"target");
|
|
return error::kNoError;
|
|
}
|
|
if (mailbox == NULL) {
|
|
return error::kOutOfBounds;
|
|
}
|
|
DoProduceTextureDirectCHROMIUM(texture, target, mailbox);
|
|
return error::kNoError;
|
|
}
|
|
|
|
void GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM(GLuint client_id,
|
|
GLenum target, const GLbyte* data) {
|
|
TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureDirectCHROMIUM",
|
|
"context", logger_.GetLogPrefix(),
|
|
"mailbox[0]", static_cast<unsigned char>(data[0]));
|
|
|
|
ProduceTextureRef("glProduceTextureDirectCHROMIUM", GetTexture(client_id),
|
|
target, data);
|
|
}
|
|
|
|
void GLES2DecoderImpl::ProduceTextureRef(const char* func_name,
|
|
TextureRef* texture_ref,
|
|
GLenum target,
|
|
const GLbyte* data) {
|
|
// ** mailbox is still a pointer to shared memory **
|
|
const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
|
|
DLOG_IF(ERROR, !mailbox.Verify()) << func_name << " was passed a "
|
|
"mailbox that was not generated by "
|
|
"GenMailboxCHROMIUM.";
|
|
|
|
if (!texture_ref) {
|
|
LOCAL_SET_GL_ERROR(
|
|
GL_INVALID_OPERATION, func_name, "unknown texture for target");
|
|
return;
|
|
}
|
|
|
|
Texture* produced = texture_manager()->Produce(texture_ref);
|
|
if (!produced) {
|
|
LOCAL_SET_GL_ERROR(
|
|
GL_INVALID_OPERATION, func_name, "invalid texture");
|
|
return;
|
|
}
|
|
|
|
if (produced->target() != target) {
|
|
LOCAL_SET_GL_ERROR(
|
|
GL_INVALID_OPERATION, func_name, "invalid target");
|
|
return;
|
|
}
|
|
|
|
group_->mailbox_manager()->ProduceTexture(mailbox, produced);
|
|
}
|
|
|
|
void MailboxManagerImpl::ProduceTexture(const Mailbox& mailbox,
|
|
Texture* texture) {
|
|
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
|
|
if (it != mailbox_to_textures_.end()) {
|
|
if (it->second->first == texture)
|
|
return;
|
|
TextureToMailboxMap::iterator texture_it = it->second;
|
|
mailbox_to_textures_.erase(it);
|
|
textures_to_mailboxes_.erase(texture_it);
|
|
}
|
|
InsertTexture(mailbox, texture);
|
|
}
|
|
|
|
void MailboxManagerImpl::InsertTexture(const Mailbox& mailbox,
|
|
Texture* texture) {
|
|
texture->SetMailboxManager(this);
|
|
TextureToMailboxMap::iterator texture_it =
|
|
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
|
|
// ** modify mailbox at this point **
|
|
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
|
|
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
|
|
}
|
|
|
|
We can leverage this for memory corruption in the GPU process by a slightly roundabout route; since each entry in the mailbox_to_textures_ has an iterator to an entry in textures_to_mailboxes_, and it is an expected invariant that both of these entries have the same mailbox name. By starting to create a mailbox named aaaa...aaaa and waiting until the first insert is complete before changing the mailbox name to AAAA...aaaa, then adding a second entry with the same texture reference but with the actual name aaaa...aaaa we get the following situation (example trace through the code from ProduceTexture with InsertTexture call inlined):
|
|
|
|
// first entry - mailbox.name = 'aaaa...aaaa', texture = t1
|
|
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
|
|
// if body not executed
|
|
if (it != mailbox_to_textures_.end()) {}
|
|
texture->SetMailboxManager(this);
|
|
TextureToMailboxMap::iterator texture_it =
|
|
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
|
|
// modify - mailbox.name = 'AAAA...aaaa'
|
|
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
|
|
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
|
|
|
|
// mailbox_to_textures_ textures_to_mailboxes_
|
|
// AAAA...aaaa, it ------------------------------> aaaa...aaaa, t1
|
|
|
|
// second entry - mailbox.name = 'aaaa...aaaa', texture = t1
|
|
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
|
|
// if body not executed (since 'AAAA...aaaa' != 'aaaa...aaaa')
|
|
if (it != mailbox_to_textures_.end()) {}
|
|
texture->SetMailboxManager(this);
|
|
TextureToMailboxMap::iterator texture_it =
|
|
textures_to_mailboxes_.insert(std::make_pair(texture, mailbox));
|
|
// texture_it is the same as before; since there already exists the pair
|
|
// 'aaaa...aaaa', t1* in textures_to_mailboxes, the insert returns an
|
|
// iterator to the existing element.
|
|
mailbox_to_textures_.insert(std::make_pair(mailbox, texture_it));
|
|
DCHECK_EQ(mailbox_to_textures_.size(), textures_to_mailboxes_.size());
|
|
|
|
// mailbox_to_textures_ textures_to_mailboxes_
|
|
// AAAA...aaaa, it ------------------------------> aaaa...aaaa, t1
|
|
// aaaa...aaaa, it -----------/
|
|
// so both entries in mailbox_to_textures_ have the same iterator.
|
|
|
|
// third entry - mailbox.name = 'aaaa...aaaa', texture = t2
|
|
MailboxToTextureMap::iterator it = mailbox_to_textures_.find(mailbox);
|
|
// this time we find an entry
|
|
if (it != mailbox_to_textures_.end()) {
|
|
// t1 != t2
|
|
if (it->second->first == texture)
|
|
return;
|
|
// so we remove the previous entry for aaaa...aaaa
|
|
TextureToMailboxMap::iterator texture_it = it->second;
|
|
mailbox_to_textures_.erase(it);
|
|
textures_to_mailboxes_.erase(texture_it);
|
|
}
|
|
|
|
// mailbox_to_textures_ textures_to_mailboxes_
|
|
// AAAA...aaaa, it ------------------------------> ??
|
|
// aaaa...aaaa, it ------------------------------> aaaa...aaaa, t2
|
|
|
|
Leaving mailbox AAAA...aaaa with a dangling reference to a no-longer valid iterator into textures_to_mailboxes_; (std::map and std::multimap iterators are invalidated by a call to erase() the element that they reference). The attached poc then calls some further methods on the mailbox to trigger a use of the dangling iterator that is detectable by ASAN.
|
|
|
|
Updated POC to work on the latest asan linux build, command buffer ids were out of date.
|
|
|
|
|
|
Proof of Concept:
|
|
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/39961.zip |