You'll have to verify the entire chain from CM source to client side interpretation to see where this conversion is happening; you've already verified that the HTML encoded characters are sent from the CD server so it's not a client side issue.
That leaves as potential culprits:
- your ASP.Net web application
- the Tridion broker libraries (assuming you use these)
- the Tridion deployer (or a custom deployer in case you have one)
- the Tridion transport mechanism
- the DD4T templates (or your own modified version of these if applicable)
- any event system or automatic workflow activities (if you have any of these)
- the CM WebGUI
- your editors
I'd start from the bottom of this list and verify that the content stored in Tridion doesn't actually contain the character references (but the real UTF-8 characters). If it's wrong here either an event system, the CM WebGUI or your editors are causing the issue.
If things look good here; check the broker database content (note that this is encoded in UTF-16 for component presentations in 2013 and higher; so try with the page content first maybe which should still be human readable). If it's wrong here either the DD4T templates or the transport service or the deployer are causing the issue.
If it is still good there the issue must be with either your ASP.Net web application of the broker libraries.
The most likely candidate would be the ASP.Net web application as any HttpServerUtility.HtmlEncode
method call (or something similar) on the content can potentially cause this.