Today, we are going to explore a new vulnerability called “Type Confusion” and as the name indicates this is a logical bug which results from a confusion between object types.
First we need to know about C++ Casting operations and there are 3 main types of them.
C++ Casting Operations:
1- Static Casting –> static_cast<ToClass>(Object)
- Class hierarchy check at compile time
2- Dynamic Casting –> dynamic_cast<ToClass>(Object)
- Run-time check based on allocated type (vtable pointer)
- Not used in performance critical code
3- C-style Casting –> (ToClass) (Object)
- C-style cast, no check for the object type at all
Type Confusion bugs arises from illegal down-casts
Up-casting (Widening):
- Cast subclass to base class
- Done automatically
Down-casting (Narrowing):
- Cast base class to subclass
- Need explicit cast
Child1 *c = new Child1(); Parent *p = static_cast<Parent*>(c); //Up-casting Child2 *d = static_cast<Child2*>(p); //Down-casting
How can we exploit type confusion bugs?
Fundamentally we need to control two pointers of different types to the same memory area
Simple Exploitation Demo
#include <iostream> using namespace std; class Base {}; // Parent Class class Execute: public Base { // Child of Base Class public: virtual void exec(const char *program) { system(program); } }; class Greeter: public Base { // Child of Base Class public: virtual void sayHi(const char *str) { cout << str << endl; } }; int main() { Base *b1 = new Greeter(); Base *b2 = new Execute(); Greeter *g; g = static_cast<Greeter*>(b1); // Safe Casting to the same type "Greeter" g->sayHi("Greeter says hi!"); // String passed to sayHi() function g = static_cast<Greeter*>(b2); // Unsafe Casting to sibling class "Execute" g->sayHi("/usr/bin/xcalc"); // String passed to exec() function // which will turn into a command to execute calculator delete b1; delete b2; return 0; }
Let’s compile this simple c++ program and run it
g++ typeConfusion_Example.cpp -o typeConfusion_Example
And boom you got a command execution!
Leave a Reply