Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parseRawEvent can allocate an unbounded amount of memory #126

Closed
brandonweeks opened this issue Oct 8, 2019 · 2 comments · Fixed by #127
Closed

parseRawEvent can allocate an unbounded amount of memory #126

brandonweeks opened this issue Oct 8, 2019 · 2 comments · Fixed by #127
Assignees

Comments

@brandonweeks
Copy link
Member

@brandonweeks brandonweeks commented Oct 8, 2019

var h rawEventHeader
if err = binary.Read(r, binary.LittleEndian, &h); err != nil {
    return event, err
}
data := make([]byte, int(h.EventSize))

In this code path an attacker can control the number of allocated bytes. This can lead to a DoS attack by OOMing the process.

Example:

Mzk0MDIwMDYxOTYzOTQ0NzkyMTIyNzkwNDAxbUfvv70AMDAxNDM2MTM4MDUwNzk3MzkyNzA0NjU0
NDY2Njc5NDgyOTM0MDQyNDU3MjE3NzE0OTY4NzAzMjkwNDcyNjYwODgyNTg5MzgwMDE4NjE2MDY5
NzMxMTIzMTk=

Produces:

rawEventHeader{
    PCRIndex:0x30343933, 
    Type:0x36303032, 
    Digest:[20]uint8{0x31, 0x39, 0x36, 0x33, 0x39, 0x34, 0x34, 0x37, 0x39, 0x32, 0x31, 0x32, 0x32, 0x37, 0x39, 0x30, 0x34, 0x30, 0x31, 0x6d},
    EventSize:0xbdbfef47,
}

0xbdbfef47 being 3.183 GB.

It doesn't appear that the TCG EFI Protocol Specification defines a maximum size for an event. So it seems our options are either choosing an arbitrary maximum or reporting this to the TCG as undefined behavior.

@ericchiang

This comment has been minimized.

Copy link
Member

@ericchiang ericchiang commented Oct 8, 2019

Nice catch :)

What about adding a check to ensure h.EventSize isn't bigger than the remaining bytes in the measurement log?

func parseRawEvent(r *bytes.Buffer) (event rawEvent, err error) {
	var h rawEventHeader
	if err = binary.Read(r, binary.LittleEndian, &h); err != nil {
		return event, err
	}
	if h.EventSize > uint32(r.Len()) {
		return event, fmt.Errorf("event size (%d) was greater than remaining bytes in measurement log (%d)", h.EventSize, r.Len())
	}
	data := make([]byte, int(h.EventSize))
	if _, err := io.ReadFull(r, data); err != nil {
		return event, err
	}
	return rawEvent{
		typ:     EventType(h.Type),
		data:    data,
		index:   int(h.PCRIndex),
		digests: [][]byte{h.Digest[:]},
	}, nil
}
@ericchiang

This comment has been minimized.

Copy link
Member

@ericchiang ericchiang commented Oct 8, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.