I've always been concerned with security and I've always stressed the importance of auditing the REAL user context not just the current user (see this post on EXECUTE AS and auditing). So, I generally try to avoid using dynamic string execution and if necessary create well tested/protected parameters (fyi – using QUOTENAME can be a fantasic solution to protectng identifiers as input parameters but it can't protect more complex strings).
Having said that, what if I'm looking at a database for the first time… just poking around trying to see if there's anything that needs further attention? I've come up with a quick query… And, while it's not going to "solve" your problem (as that's going to take some re-writing of code) or even truly verify if you're vulnerable, it gives you a "quick list" of where you should look first! If your code uses dynamic strings AND it's elevated – then start there!
SELECT OBJECT_NAME(object_id) AS [Procedure Name],
WHEN sm.definition LIKE '%EXEC (%' OR sm.definition LIKE '%EXEC(%' THEN 'WARNING: code contains EXEC'
WHEN sm.definition LIKE '%EXECUTE (%' OR sm.definition LIKE '%EXECUTE(%' THEN 'WARNING: code contains EXECUTE'
END AS [Dynamic Strings],
WHEN execute_as_principal_id IS NOT NULL THEN N'WARNING: EXECUTE AS ' + user_name(execute_as_principal_id)
ELSE 'Code to run as caller – check connection context'
END AS [Execution Context Status]
FROM sys.sql_modules AS sm
ORDER BY [Procedure Name]
Is this enough? Anything else you'd check? What do you think?