The Rossoneri were caught napping after four minutes as Ciro Immobile stole in for his 26th goal of the season.
Olivier Giroud levelled straight after half-time and Milan’s pressure paid off when sub Zlatan Ibrahimovic set up Sandro Tonali for the winner.
Stefano Pioli’s side are two points clear of Inter with four games left but they have played a game more.
After Inter’s comprehensive win over Roma last night, Milan knew only three points would take them back to the Serie A summit.
Conceding Immobile’s opener was the worst possible start but Pioli’s side were immediately on the front foot, only for Giroud, Barcelona-bound Franck Kessie and the impressive Rafael Leao to pass up presentable chances.
Undeterred, Giroud scored his first club goal for seven games when he turned home Leao’s cross immediately after the restart.
Pioli sent on 40-year-old Ibrahimovic and in a frantic last 10 minutes, Lazio keeper Thomas Strakosha made excellent saves from Leao and Ante Rebic.
Ibrahimovic then had a golden opportunity in the 89th minute but dallied and his wayward shot was blocked.
It looked like their title bid was stalling, but Lazio defender Adam Marusic gave the ball away, Ibrahimovic won a header and Tonali was on hand to bundle in a vital winner.