Mattia de Sciglio conceded the penalty in the 95th minute with a handball, just minutes after team-mate Jose Sosa was sent off for a second yellow card.
Medhi Benatia had given Juventus the lead on 30 minutes, before Carlos Bacca equalised two minutes before half-time.
Second-placed Roma, who have a game in hand, play Palermo on Sunday.
Juventus, who are on track for their sixth successive Scudetto, have won 31 consecutive Serie A home games.
The hosts, who lost to Milan in both the league and the Italian Super Cup final earlier in the season, had dominated the early exchanges, with Marko Pjaca and Dybala keeping Gianluigi Donnarumma busy in the Rossoneri's goal.
Juve deservedly took the lead when Dani Alves chipped the ball to the adventurous centre-back Benatia who controlled it on his chest and smashed his shot past Donnarumma from close range.
Milan hit back against the run of play, as Gerard Deulofeu counter-attacked up the left wing and played in Bacca who poked the ball beyond Gianluigi Buffon to equalise on 43 minutes.
The Rossoneri grew into the game in the second half but it was Juventus who had the better of the chances with Sami Khedira, Miralem Pjanic and Pjaca going close.
The final moments proved the most exciting as first Sosa saw red in the 93rd minute for a bad tackle on Kwadwo Asamoah.
Two minutes later Gonzalo Higuain's bicycle kick was inches wide and he then saw another shot tipped away by Donnarumma.
Then came De Sciglio's handball and Dybala kept his nerve to slot his penalty past 18-year-old Donnarumma to spark wild celebrations.
Match ends, Juventus 2, Milan 1.
Second Half ends, Juventus 2, Milan 1.
Goal!  Juventus 2, Milan 1. Paulo Dybala (Juventus) converts the penalty with a left footed shot to the top left corner.
Penalty conceded by Mattia De Sciglio (Milan) with a hand ball in the penalty area.
Attempt saved. Gonzalo Higuaín (Juventus) right footed shot from the centre of the box is saved in the centre of the goal. Assisted by Dani Alves.
Attempt missed. Gonzalo Higuaín (Juventus) right footed shot from the centre of the box is close, but misses to the left. Assisted by Leonardo Bonucci with a cross.
Second yellow card to José Sosa (Milan) for a bad foul.
Kwadwo Asamoah (Juventus) wins a free kick on the left wing.
Foul by José Sosa (Milan).
Substitution, Milan. Leonel Vangioni replaces Lucas Ocampos.
Attempt missed. Miralem Pjanic (Juventus) right footed shot from outside the box is too high from a direct free kick.
Substitution, Juventus. Moise Kean replaces Marko Pjaca.
José Sosa (Milan) is shown the yellow card for a bad foul.
Paulo Dybala (Juventus) wins a free kick in the attacking half.
Foul by José Sosa (Milan).
Sami Khedira (Juventus) is shown the yellow card for a bad foul.
Foul by Sami Khedira (Juventus).
Andrea Bertolacci (Milan) wins a free kick in the attacking half.
Paulo Dybala (Juventus) wins a free kick in the attacking half.
Foul by Andrea Bertolacci (Milan).
Attempt blocked. José Sosa (Milan) right footed shot from outside the box is blocked.
Foul by Leonardo Bonucci (Juventus).
Lucas Ocampos (Milan) wins a free kick in the attacking half.
Stephan Lichtsteiner (Juventus) wins a free kick on the right wing.
Foul by Gerard Deulofeu (Milan).
Corner,  Milan. Conceded by Leonardo Bonucci.
Substitution, Juventus. Daniele Rugani replaces Medhi Benatia.
Miralem Pjanic (Juventus) is shown the yellow card.
Foul by Gonzalo Higuaín (Juventus).
José Sosa (Milan) wins a free kick in the defensive half.
Attempt missed. Andrea Poli (Milan) right footed shot from the right side of the box is too high. Assisted by José Sosa.
Attempt saved. José Sosa (Milan) right footed shot from outside the box is saved in the bottom right corner.
Attempt missed. Leonardo Bonucci (Juventus) header from the centre of the box is too high. Assisted by Paulo Dybala with a cross following a corner.
Corner,  Juventus. Conceded by Gianluigi Donnarumma.
Attempt saved. Gonzalo Higuaín (Juventus) right footed shot from the centre of the box is saved in the bottom right corner.
Attempt saved. Sami Khedira (Juventus) right footed shot from the right side of the box is saved in the centre of the goal. Assisted by Paulo Dybala.
Stephan Lichtsteiner (Juventus) wins a free kick on the right wing.
Foul by Andrea Bertolacci (Milan).
Substitution, Milan. Andrea Poli replaces Mario Pasalic.
Attempt missed. Lucas Ocampos (Milan) left footed shot from outside the box misses to the left. Assisted by Andrea Bertolacci.
Paulo Dybala scored a 97th-minute penalty to give Juventus a dramatic win over AC Milan and extend their lead at the top of Serie A to 11 points.