CPE, qui signifie Common Platform Enumeration, est un système normalisé de dénomination du matériel, des logiciels et des systèmes d'exploitation. CPE fournit un schéma de dénomination structuré pour identifier et classer de manière unique les systèmes informatiques, les plates-formes et les progiciels sur la base de certains attributs tels que le fournisseur, le nom du produit, la version, la mise à jour, l'édition et la langue.
CWE, ou Common Weakness Enumeration, est une liste complète et une catégorisation des faiblesses et des vulnérabilités des logiciels. Elle sert de langage commun pour décrire les faiblesses de sécurité des logiciels au niveau de l'architecture, de la conception, du code ou de la mise en œuvre, qui peuvent entraîner des vulnérabilités.
CAPEC, qui signifie Common Attack Pattern Enumeration and Classification (énumération et classification des schémas d'attaque communs), est une ressource complète, accessible au public, qui documente les schémas d'attaque communs utilisés par les adversaires dans les cyberattaques. Cette base de connaissances vise à comprendre et à articuler les vulnérabilités communes et les méthodes utilisées par les attaquants pour les exploiter.
Services & Prix
Aides & Infos
Recherche de CVE id, CWE id, CAPEC id, vendeur ou mots clés dans les CVE
The IOHIDFamily API in Apple iOS before 9.2, OS X before 10.11.2, tvOS before 9.1, and watchOS before 2.1 allows attackers to execute arbitrary code in a privileged context or cause a denial of service (memory corruption) via a crafted app, a different vulnerability than CVE-2015-7111.
Improper Restriction of Operations within the Bounds of a Memory Buffer The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Métriques
Métriques
Score
Gravité
CVSS Vecteur
Source
V2
9.3
AV:N/AC:M/Au:N/C:C/I:C/A:C
nvd@nist.gov
EPSS
EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.
Score EPSS
Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.
Date
EPSS V0
EPSS V1
EPSS V2 (> 2022-02-04)
EPSS V3 (> 2025-03-07)
EPSS V4 (> 2025-03-17)
2022-02-06
–
–
6.55%
–
–
2022-02-13
–
–
6.55%
–
–
2022-04-03
–
–
6.55%
–
–
2023-03-12
–
–
–
0.29%
–
2023-06-18
–
–
–
0.29%
–
2023-11-05
–
–
–
0.29%
–
2023-11-12
–
–
–
0.29%
–
2023-11-19
–
–
–
0.29%
–
2023-12-03
–
–
–
0.29%
–
2023-12-17
–
–
–
0.29%
–
2024-02-11
–
–
–
0.29%
–
2024-04-07
–
–
–
0.29%
–
2024-06-02
–
–
–
0.29%
–
2024-09-15
–
–
–
0.29%
–
2024-09-22
–
–
–
0.29%
–
2024-10-06
–
–
–
0.41%
–
2024-12-08
–
–
–
0.41%
–
2024-12-22
–
–
–
0.41%
–
2025-01-05
–
–
–
0.41%
–
2025-01-19
–
–
–
0.41%
–
2025-03-18
–
–
–
–
33.34%
2025-03-30
–
–
–
–
37%
2025-03-30
–
–
–
–
37,%
Percentile EPSS
Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.
Date de publication : 2016-01-27 23h00 +00:00 Auteur : Google Security Research EDB Vérifié : Yes
Source: https://code.google.com/p/google-security-research/issues/detail?id=542
The IOHIDLibUserClient allows us to create and manage IOHIDEventQueues corresponding to available HID devices.
Here is the ::start method, which can be reached via the IOHIDLibUserClient::_startQueue external method:
************ SNIP **************
void IOHIDEventQueue::start()
{
if ( _lock )
IOLockLock(_lock);
if ( _state & kHIDQueueStarted )
goto START_END;
if ( _currentEntrySize != _maxEntrySize ) <--- (a)
{
mach_port_t port = notifyMsg ? ((mach_msg_header_t *)notifyMsg)->msgh_remote_port : MACH_PORT_NULL;
// Free the existing queue data
if (dataQueue) { <-- (b)
IOFreeAligned(dataQueue, round_page_32(getQueueSize() + DATA_QUEUE_MEMORY_HEADER_SIZE));
}
if (_descriptor) {
_descriptor->release();
_descriptor = 0;
}
// init the queue again. This will allocate the appropriate data.
if ( !initWithEntries(_numEntries, _maxEntrySize) ) { (c) <----
goto START_END;
}
_currentEntrySize = _maxEntrySize;
// RY: since we are initing the queue, we should reset the port as well
if ( port )
setNotificationPort(port);
}
else if ( dataQueue )
{
dataQueue->head = 0;
dataQueue->tail = 0;
}
_state |= kHIDQueueStarted;
START_END:
if ( _lock )
IOLockUnlock(_lock);
}
************ SNIP **************
If _currentEntrySize is not equal to _maxEntrySize then the start method will attempt to reallocate a better-sized queue;
if dataQueue (a member of IODataQueue) is non-zero its free'd then initWithEntries is called with the new _maxEntrySize.
Note that the error path on failure here jumps straight to the end of the function, so it's up to initWithEntries to
clear dataQueue if it fails:
************ SNIP **************
Boolean IOHIDEventQueue::initWithEntries(UInt32 numEntries, UInt32 entrySize)
{
UInt32 size = numEntries*entrySize;
if ( size < MIN_HID_QUEUE_CAPACITY )
size = MIN_HID_QUEUE_CAPACITY;
return super::initWithCapacity(size);
}
************ SNIP **************
There's a possible overflow here; but there will be *many* possible overflows coming up and we need to overflow at the right one...
This calls through to IOSharedDataQueue::initWithCapacity
************ SNIP **************
Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
{
IODataQueueAppendix * appendix;
vm_size_t allocSize;
if (!super::init()) {
return false;
}
_reserved = (ExpansionData *)IOMalloc(sizeof(struct ExpansionData));
if (!_reserved) {
return false;
}
if (size > UINT32_MAX - DATA_QUEUE_MEMORY_HEADER_SIZE - DATA_QUEUE_MEMORY_APPENDIX_SIZE) {
return false;
}
allocSize = round_page(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE);
if (allocSize < size) {
return false;
}
dataQueue = (IODataQueueMemory *)IOMallocAligned(allocSize, PAGE_SIZE);
************ SNIP **************
We need this function to fail on any of the first four conditions; if we reach the IOMallocAligned call
then dataQueue will either be set to a valid allocation (which is uninteresting) or set to NULL (also uninteresting.)
We probably can't fail the ::init() call nor the small IOMalloc. There are then two integer overflow checks;
the first will only fail if size (a UInt32 is greater than 0xfffffff4), and the second will be impossible to trigger on 64-bit since
round_pages will be checking for 64-bit overflow, and we want a cross-platform exploit!
Therefore, we have to reach the call to initWithCapacity with a size >= 0xfffffff4 (ie 12 possible values?)
Where do _maxEntrySize and _currentEntrySize come from?
When the queue is created they are both set to 0x20, and we can partially control _maxEntrySize by adding an new HIDElement to the queue.
_numEntries is a completely controlled dword.
So in order to reach the exploitable conditions we need to:
1) create a queue, specifying a value for _numEntries. This will allocate a queue (via initWithCapacity) of _numEntries*0x20; this allocation must succeed.
2) add an element to that queue with a *larger* size, such that _maxEntrySize is increased to NEW_MAX_SIZE.
3) stop the queue.
4) start the queue; at which point we will call IOHIDEventQueue::start. since _maxEntrySize is now larger this
will free dataQueue then call initWithEntries(_num_entries, NEW_MAX_SIZE). This has to fail in exactly the manner
described above such that dataQueue is a dangling pointer.
5) start the queue again, since _maxEntrySize is still != _currentEntrySize, this will call free dataQueue again!
The really tricky part here is coming up with the values for _numEntries and NEW_MAX_SIZE; the constraints are:
_numEntries is a dword
(_numEntries*0x20)%2^32 must be an allocatable size (ideally <0x10000000)
(_numEntries*NEW_MAX_SIZE)%2^32 must be >= 0xfffffff4
presumable NEW_MAX_SIZE is also reasonably limited by the HID descriptor parsing code, but I didn't look.
This really doesn't give you much leaway, but it is quite satisfiable :)
In this case I've chosen to create a "fake" hid device so that I can completely control NEW_MAX_SIZE, thus the PoC requires
root (as did the TAIG jailbreak which also messed with report descriptors.) However, this isn't actually a requirement to hit the bug; you'd just need to look through every single HID report descriptor on your system to find one with a suitable report size.
In this case, _numEntries of 0x3851eb85 leads to an initial queue size of (0x3851eb85*0x20)%2^32 = 0xa3d70a0
which is easily allocatable, and NEW_MAX_SIZE = 0x64 leads to: (0x3851eb85*0x64)%2^32 = 0xfffffff4
To run the PoC:
1) unzip and build the fake_hid code and run 'test -k' as root; this will create an IOHIDUserDevice whose
cookie=2 IOHIDElementPrivate report size is 0x64.
2) build and run this file as a regular user.
3) see double free crash.
There's actually nothing limiting this to a double free, you could go on indefinitely free'ing the same pointer.
As I said before, this bug doesn't actually require root but it's just *much* easier to repro with it!
Testing on: MacBookAir5,2 10.10.5 14F27
Guessing that this affects iOS too but haven't tested.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/39379.zip