Sergio Conceicao's side were demolished 5-1 by Liverpool in their previous European outing, while Stefano Pioli's men suffered last-minute heartbreak against Atletico Madrid to leave both sides winless from their first two Group B games.
Diaz looked to seize the early initiative but was denied by the woodwork after just four minutes, with Medhi Taremi then spurning a series of chances.
However, Diaz managed to break the deadlock at Estadio do Dragao after the interval to condemn Milan to consecutive European away defeats for the first time since April 2012.
Diaz almost offered the hosts the perfect start, the Colombia international drilling a low drive against the left post before Taremi curled narrowly wide.
Olivier Giroud then misdirected a header after Rafael Leao's cross created Milan's first presentable opportunity, with Taremi missing a headed chance of his own before poking wide as Porto failed to make their first-half dominance pay.
Taremi remained persistent in his pursuit of the opener after the interval, dragging a left-footed strike narrowly off target after capitalising on Fikayo Tomori's mistake.
Tomori made amends with a last-ditch block to deny Otavio before Mateus Uribe arrowed just the wrong side of the left-hand post, but Porto did not have to wait much longer for their deserved opener.
The visitor felt Ismael Bennacer was fouled by Taremi in the build-up but referee Felix Brych disagreed as Diaz fired into the bottom-right corner after 65 minutes, with Pepe angling a rare left-footed effort wide three minutes later.
Pioli's team never looked like finding a late equaliser as Porto recorded their seventh clean sheet in its last eight group-stage matches in the competition.