The Swedish striker solidified his position as the league's top scorer with a brace after the table-toppers went into the half-time break trailing to Pablo Osvaldo's opener.
A penalty early in the second period for a handball by Gabriel Heinze allowed Ibrahimovic to equalise, before he turned the result around seven minutes from time with a headed finish to his own chip over visiting goalkeeper Maarten Stekelenburg.
The result extends Milan's lead to seven points, having played a game more than second-placed Juventus who take on Inter Milan on Sunday, while Roma remain in the top six despite the defeat.
Though the title-chasing hosts controlled the early stages, serious efforts on goal at either end were few and far between.
The first big moment of the match came on 11 minutes when Ibrahimovic’s fierce drive from a 25-yard free kick had to be tipped over the bar by Stekelenburg.
Stephan El Shaarawy, a constant thorn in Roma’s side on the left flank, cut inside on 41 minutes to curl a low shot from just outside the area onto the far post, with both Ibrahimovic and Antonio Nocerino unable to react quickly enough to convert the rebound.
From there, the visitors went on to enjoy their best five-minute spell of the first half right at its climax, with Fabio Borini firing off-target before almost heading for Osvaldo to finish from two yards.
The Argentine-born Italian would soon get his goal, however, as Milan failed to clear their lines from a subsequent Roma attack and Daniele De Rossi’s first-time effort from inside the ‘D’ was prodded past Christian Abbiati by the striker.
The home side struggled to shake off their complacency as the second half began: Abbiati almost gifted Francesco Totti with a poor kick-out, before making up for the error by saving well from Marquinhos out on the left.
But within a minute of their latest flurry of opportunities to double the advantage, Roma found themselves facing a penalty when Massimo Ambrosini’s cross caught the hand of Heinze, earning the Argentine defender a booking.
Ibrahimovic sent Stekelenburg the wrong way from 12 yards, and suddenly Milan were alive once more with further chances for Ibrahimovic and Djamel Mesbah followed by Sulley Muntari rattling the bar with a half-volley after muscling past Simon Kjaer.
Though Roma were still looking for ways to re-take the lead, they were unable to find that final ball and on 83 minutes they found themselves behind.
Phillipe Mexes’ raking ball upfield was brought down by Ibrahimovic, who through on goal chipped the out-rushing Stekelenburg before heading the ball over the line before it could fall short of goal or be cleared by the recovering Kjaer.