The match kicked off at 17:15 local time with the temperature around 32 Celsius and, although the pitch was almost entirely in the shade, the conditions clearly affected both teams.
After an entirely forgettable first half, Milan, still missing forward Zlatan Ibrahimovic with a calf injury, finally stirred into life after the break as Hakan Calhanoglu and Lucas Paqueta forced saves from Antonio Mirante.
The hosts broke through in the 76th minute when Franck Kessie's shot was saved at close range by Mirante and the ball rebound to Ante Rebic. His first shot struck the post but the ball came straight back to him and he scored at the second attempt.
Calhanoglu converted a penalty in the 89th minute to give Milan their second straight win since the restart of Serie A. They stayed seventh with 42 points, six behind fifth-placed Roma.
"The kickoff time made this a really tough match," said Milan coach Stefano Pioli. "We were looking for a victory against one of the top sides and we got it on merit. This win gives us confidence for the future. We have to grit our teeth and try to finish the championship well."
Roma coach Paulo Fonseca pointed out that Milan played their previous match on Monday while his team were in action on Wednesday, when they came from behind to beat Sampdoria 2-1.
"We gifted them the match with our mistakes," he said. "Teams are not creating many chances at the moment, but we are presenting them to our opponents and that makes everything more difficult."