Portuguese star Danny made the difference for Luciano Spalletti's victorious visitors, as the Rossoneri's Group C campaign comes to a disappointing close
Having rested several first-team players, the hosts failed to click and were punished in the first half when the Portuguese playmaker swooped on a rebound for the only goal of the game.
Zenit were the team most in need of a win at San Siro as the two sides kicked off, after Milan secured second spot in Group C and a place in the last 16 on matchday 5.
The Russians, on the other hand, knew that three points would guarantee them a consolation prize of Europa League football after Christmas, and also up for grabs was a first victory on Italian soil for the club.
Despite this, however, the game began in an even fashion. Both Milan and Zenit played fluid, passing football and attempted to keep possession, although clear-cut chances were at a premium in the opening stages.
The Rossoneri, though, were convinced they had earned a penalty when Giampaolo Pazzini went down under Bruno Alves' challenge, but their protests were in vain as the referee was having none of it. Urby Emanuelson also went close for the hosts, flashing a venomous shot just past the post with 15 minutes on the clock.
Milan enjoyed the lion's share of possession during the first half, but it was to be the visitors who took the lead. Massimo Ambrosini did well to stop Sergei Semak in his tracks with a tackle in the Italian penalty area, but his defence were painfully slow to react as the ball ran free. The first man to reach it was the impressive Danny, who artfully curled the ball past the despairing dive of Christian Abbiati to put Luciano Spalletti's men in the ascendancy.
The goal served as a wake-up call for the home team, who started to commit more bodies into attack. Bojan Krkic was not far away with an ambitious overhead kick that went just wide of the post, while Mathieu Flamini called goalkeeper Viacheslav Malafeev into action with a stinging effort from outside the area that was parried by the Zenit man.
The Russians held on to go into the break one goal up, and with Anderlecht trailing against Malaga, the Europa League appeared within their grasp. Seven minutes into the second half, though, Massimiliano Allegri's charges looked certain to restore parity.
A well-worked counter ended with Pazzini diverting Kevin-Prince Boateng's cross towards Malakeev, who reacted smartly to hack the ball away with his feet. Emanuelson was in prime position to convert the rebound, but a momentary hesitation from the winger was enough for Zenit to clear their lines and keep their lead intact.
The pressure continued to build from the home team, who had almost complete control of possession as they probed for an equaliser. Krkic tried his luck from deep with a shot that flew over the bar, while Zenit began to defend in numbers in an effort to protect their slender advantage.
The deep backline was paying off for Spalletti's troops, who forced Milan out of their box and into shooting desperately from range in the absence of better alternatives. Despite close calls for substitutes Robinho and Stephan El Shaarawy, who both caused scares, the Russians were able to play out a narrow win to mark their first success on Italian soil.