Massimiliano Allegri's men missed the chance to leapfrog Serie A leaders Juventus following two late goals from the Biancocelesti at the Stadio Olimpico on Wednesday
A tense match was blown open by Hernanes’ second-half strike, before Tommaso Rocchi made the points safe five minutes from time.
The visitors attacked from the opening whistle as Federico Marchetti was forced into a great save in the early going after Zlatan Ibrahimovic’s cross set up Antonio Nocerino for a header.
Lazio went close to taking the lead themselves not long after but Matuzalem's low shot went inches past Christian Abbiati’s post.
Giuseppe Biava had claims for a penalty after he felt Thiago Silva prevented him from latching on to a corner, only for the referee to wave play on.
As the half wore on, the visitors began to create chances of their own. Ibrahimovic sent Stephan El Shaarawy clear. The Italian managed to evade the onrushing Marchetti, but was forced wide and missed his opportunity.
Minutes later Ibrahimovic himself was through, but, perhaps with the previous incident in mind, chose not to square the ball to the better-placed El Shaarawy. His hesitance cost him and the Swede wasn’t even able to win a corner for his side.
The start of the second half brought immediate controversy. Ibrahimovic flicked the ball on to El Shaarawy, only for Andre Dias stuck out a hand and palm the ball away. The referee immediately pointed to the spot, only for his assistant to overrule the decision.
Deflated by the decision, it took Milan some time to get back in the match. Massimo Ambrosini carved out a couple of half chances, sending a shot narrowly wide, before his advancing years let him down, with Marchetti capitalising on his lack of pace to claim the ball at the veteran's feet.
Lazio started to respond, however. Hernanes charged into the Milan box, superbly leaving Alessandro Nesta in his wake, until Ignazio Abate came across as the Brazilian was preparing to pull the trigger.
At the other end, Robinho played the ball across the face of goal. It hit Biava, but Marchetti stuck out an arm to palm the ball away when it seemed like a certain goal, and Ibrahimovic couldn’t snuff the ball over the line.
Seconds later, the champions were behind. Rocchi played a neat ball into the box to Hernanes, who hooked the ball around Nesta and past Abbiati to put the hosts ahead.
A shell-shocked Milan almost found themselves two goals behind minutes later as Hernanes squandered a golden chance, sending the ball wide of the far post.
Lazio sealed the victory five minutes from time, with Rocchi smashing home Senad Lulic’s pull-back.
Ibrahimovic wasted a late chance to pull a goal back, but it was too late. It was Lazio’s first league victory over Milan since February 1998, a result that puts a serious dent in the San Siro side’s chances of retaining their title.