Basically you just have a pointer:
p1 -> [Object 1]
And someone holds access to p1 even after you free p1, so now:
p1 -> [Junk]
The security flaw is when that memory is reclaimed for some use, so now:
p1 -> [Object 2]
And the malicious holder has free access to the properties of the new object.