Does the following lead to undefined behavior as long as the pointer being used to access the pointer-to-member is of a correct type?
No, it's well formed. The rule, from [expr.mptr.oper] is:
If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.
The dynamic type of *this is sub, which does contain the member, so this is fine.
And if so, why do I need the cast?
Because it's an inherently unsafe cast, and the rule of thumb is that inherently unsafe operations should be loud and visible. In this specific case, it's fine, but that's only because you were being careful. Requiring the cast forces you to have to think about it.
A simpler example might be to look at just the pointers instead of the pointer-to-member. In a simple hierarchy (assuming public, non-ambiguous, etc.), it is always safe to cast a Derived* to a Base*. There's nothing problematic there, so you don't need to write a cast. However, it is not always safe to cast a Base* to a Derived*... you might not have a Derived* there. But, it's not never safe - disallowing that cast entirely would be bad. So the safe cast is implicit, but the unsafe cast must be explicit.
fooon an object that doesn't have theintmember, so just don't do that. Put another way, knowing that it's not formally UB, if it isn't, doesn't help with the real problem, the type unsafety, so the UB or not is pretty irrelevant other than as a language lawyer question (but if that's your interest then consider tagging the question as such). What is the problem you're trying to solve this way?