People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
PCoIP or WSP (Workspaces Streaming Protocol. WSP uses many third party libraries in order to make the virtual PC feel like it is more physical than it really is, such as USB over Ethernet by Eltima SDK.IRP_MJ_DEVICE_CONTROL packet, the input and output data depend on the IOCTL code that is invoked. The CONTROL CODE is a 32-bit value with several fields, including the field TransferType. NtDeviceIoControlFile syscall will return data. There are three different modes for this: METHOD_BUFFERED, METHOD_IN/OUT_DIRECT and METHOD_NEITHER. The first one will copy the caller input data into the user provided buffer. The second version will supply an memory descriptor list (MDL) and ensures that our thread has access to this information. The final one takes in a user-mode address and reads/writes into this with no validation. Of course, the driver uses the insecure METHOD_NEITHERMETHOD_NEITHER by itself is NOT secure. However, the IOCTL handler is responsible for validating, probing, locking and mapping the buffer, depending on the use case. Since this is the case, double fetches, TOCTOUs, bad pointer dereferences and other vulnerabilities may be possible to exploit. Although this is not a vulnerability by itself, it is a code smell that should be checked out. bpf_ringbuf_map and the other is bpf_ringbuf. bpf_ringbuf_map contains a pionter to the bpf_ringbuf. bpf_ringbuf contains a consumer and producer position alignment and page aligned data, where this memory is mapped twice to give a ring buffer feel. In the eBPF bytecode, the data has a memory allocation for the data; this is essentially a call to malloc in the eBPF world but has to be a static value. The verifier knows this value because it is passed in as a const during the verification process. mmaped directly with the data not being validated after this alteration. The main check, mentioned above, can then be manipulated to pass by altering the producer and consumer position values so that the eBPF allocation goes much too large for the memory given to it. This leads to an out of bounds read and out of bounds write in the kernel. bpf_ringbuf structures and a kernel stack for exploitation. This is achieved by creating huge maps and then spawning a bunch of processes. Eventually, this lines up the way the attacker wants. Once the memory feng shui is done, the out of bounds read can be used to leak kernel pointers from the bpf_ringbuf object. read and waiting to write to the buffer. With a full ROP chain setup, with user controllable values from the primitive above, popping a root shell is trivial. read syscall function call does not have to be adjacent to our block. This is because we can search for the address of read until we find the kernel address that it would be at until the end of the function. That is super neat and takes out a lot of the system randomness. InstructionSelector::VisitChangeInt32ToInt64 converts a 32 bit integer into a 64-bit integer by either sign extending or padding the value with 0s. ArrayPrototypePop and ArrayPrototypeShift.Array.shift removes the first element from the array, returns the removed element then computes the new size of the array by subtracting one. By abusing the original vulnerability and using it for the size of an array, the confusion is created. By running Array.shift, the length of the array will become -1, since there is no bounds check at this point in the optimization as everything is supposed to be safe. addrof (address of) and fakeobj (fake object) primitives. wasm function they created. Since the wasmep_loop_check_proc is trying to increment a reference count of a file in the Linux kernel via a call to get_file(). However, get_file() does not do the proper sanity checks on the file prior to access: only get_file_rcu() does. epoll Linux subsystem, this becomes a problem because ep_loop_check_proc only has a weak reference to the file. Since this weak reference is NOT enough from it being deleted, it can be deleted while being used in ep_loop_check_proc. This created a use after free on the object. Even though this leads to a use after free, the author of the post labels this as a object state confusion bug. fd to epoll, the deletion does not occur concurrently to this. The attempted fix was to check the reference count of the file via get_file, which is where the bug was introduced at.runc and libcontainer are what makes Docker, Docker. This handles all of the chroot, namespaces and everything else in between. Docker adds a nice wrapper around all of this to make it more practical to use and install things. runc is written in GoLang and libcontainer is written in C.runc about the bind mounts via a Go to C call, the Go string can have embedded nullbytes inside of it.hostpath restrictions in Kubernetes clusters. uint16 for the length of the message and a byte[] for the bytes themselves. Even though this looks totally fine, the length can be overflowed! This resulted in another smuggling bug since we can now specify all of the data in a message, even though we should not be able to. CLONE_FLAGS_ATTR. This would give the container access to the host namespace.http and file. However, many applications create their own in order to allow for extra functionality inside of the application. The authors of this article went after the common URI handlers on Windows 10 to see if they could find any vulnerabilities. ms-officecmd. Since Office is crazy complex, this was a legacy protocol and would be installed everywhere, they started looking around this URI handling. The URI accepted valid JSON, with a simply payload being ms-officecmd:{}.ms-officeapp:), they were able to get a valid payload to work. Thefile:// was blocked, using C:// bypassed this validation to access a local file. Additionally, by adding a trailing / the file extension check is bypassed but is ignored once the executable is open. In the POC on the page, they should PUTTY being opened directly. If we can trick the user into downloading something, we could even run our own executable here!AppBridge.dll library handles the URI. To do this, they need to include some of the user input into a cmd argument directly. By adding a double quote (") into the filename parameter, they found this could be used to escape this parameter. As a result, argument injection was now possible for whatever application they were trying to load. --ignore-certificate-errors and an IP host rewrite rule, this could be done. Because of previous CVEs in Electron, Electron decided to not parse information after a file URI. Still though, they made an exception for 1 letter URIs. With a bogus URI and our flag above, a MITM attack could now be performed. --inspect flag could be inserted. This flag can specify a debugger port to connect to. Upon connecting exec("<command>") was executed, giving RCE on the device, assuming an attacker knew where to connect to. Another bug was a command injection via the --gpu-launcher parameter of Electron, which comes from Chrome. This trick was used in a previous exploit as well.${jndi:ldap://localhost:1389/a} that gets logged and it will make a call to this to execute arbitrary code.audio_ipi at vendor/lib/hw/audio.primary.mt6853.so. This library has a single export: AudioMessengerAPI, which is responsible for Inter-processor interrupt (IPI) messages to the audio DSP. The driver has 6 ioctls, which the authors interact with directly during the later proof of concept. audio_dsp.img. However, this also could have been done by reading the /dev/block/platform/bootdevice/by-name/audio_dsp on a root device. The article dives into the format of this img as well but they do find out it runs a custom version of FreeRTOS. Here is the interesting part though: IDA has no idea how to process a large part of this code. memcpy out of bounds write on the heap. Sending more than 20 bytes triggers the bug. AudioManager. The authors believe that this was left over for testing purposes but gives us access to more things than we should! malloc. Since the overflow occurred, the buffer is undersized! This leads to a buffer overflow inside this buffer. This should lead to a crash though, right? 32GB of data looks would be a large overflow!GList backing buffer. This buffer stores segment information and is used to find the segments to use for the writing process. By using the overflowing write to corrupt the backing buffer pointer with pointers to bitmaps, we can cause this program not to crash! Even function pointers still work properly since the bitmap type inherits from the Segment type.