To enable a codebase to be refactored, the fundamental necessity is test coverage. Ideally fast, automated test coverage. You want to be able to assert, with high confidence after every refactoring step, that you have not introduced a behavioral change. You get that confidence and make those assertions with test coverage. When you're refactoring, you're changing the internal structure, so your unit tests will also need to be refactored. However, your higher-level tests should remain stable. If you don't have robust testing or if your code isn't easily testable, characterization tests are a good way to get some test coverage to enable refactoring.
But, in my experience, most of the barriers to refactoring aren't technical. Being allowed and encouraged to spend time to improving the readability, maintainability, and testability of the codebase isn't often seen as a good investment of time. Instead, there's an ongoing drive for delivering new features for customers. However, investing in refactoring - especially if the codebase is high in technical debt - can make it faster and safer to deliver these new features and reduce the liklihood of defects in those new features.