This is exactly the behavior that you would expect to see.
You never add anything to the Hash, therefore the Hash is completely empty. When you look up a key, that key will never exist, therefore it returns the default value, which you have specified to be an Array.
So, you look up the key 'a', which doesn't exist, and thus returns the Array you specified as the default value. Then, you call << on that Array, which appends a value (1) to it.
Next, you look up the key 'b', which also doesn't exist, and thus returns the Array you specified as the default value, which now contains the element 1 you added earlier. Then, you call << on that Array, appending the value 2 to it.
You end up with a Hash that is still empty, since you never added anything to it. The default value of the Hash is now an array containing the values 1 and 2.
The output you are seeing is because IRb always prints the result of the last expression that was evaluated. The last expression in your example is calling << on the Array. << returns its receiver, which then is the return value of the entire expression and thus what IRb prints out.