The visitors sealed a spot in the Champions League last 16 in the dampest fashion, losing but going through due to Port's defeat at Atletico Madrid
The Russian side required victory to progress from Group G without relying on the outcome in the Spanish capital and Aleksandr Kerzhakov put them on course to do just that with the opener in the 35th minute.
However, Vienna scored three goals – two courtesy of Philipp Hosiner – within seven minutes either side of the break to leave Zenit facing an anxious wait before Roman Kienast added a fourth late on.
Porto were unable to recover a first-half deficit, resigning them to Europa League football and sending Zenit through to the Champions League round of 16 with only six points from six games.
Vienna, who were guaranteed to finish bottom before kick-off, celebrated their first win in Europe's elite competition, with Tomas Jun also on target.
The home side were without defender Lukas Rotpuller and midfielder Bernhard Luxbacher due to injury, while playmaker Danny missed out for Zenit.
That did not prevent the Russian heavyweights creating chances in an opening half hour they dominated.
Within 180 seconds, Hulk fired over the crossbar following a neat passing move. Domenico Criscito was then close to connecting with a Viktor Fayzulin cross, before Hulk created space for himself with some delightful footwork only to see his shot from the edge of the box blocked by Kaja Rogulj.
Zenit eventually broke the deadlock in the 35th minute. Kerzhakov's clever movement coupled with defender Manuel Ortlechner's untimely slip allowed the former to race on to Hulk's reverse through-ball. Kerzhakov took it round goalkeeper Heinz Lindner and slotted home into the empty net.
Out of nothing, however, Vienna equalised on the stroke of half-time. Hosiner robbed Zenit of possession, played a superb one-two with Marko Stankovic and slotted the ball across goalkeeper Yuri Lodygin and into the bottom corner.
Within six minutes of the restart, Vienna were 3-1 up. First, following a very poor goal kick from Lodygin, Markus Suttner controlled the ball sublimely and crossed to give Jun a tap-in.
Then Florian Mader's long-range strike was parried by Lodygin straight into the path of Hosiner, who thumped the ball home to complete his double.
Zenit tried to respond as Konstantin Zyryanov went close from distance, Hulk forced Lindner into a smart save and Axel Witsel saw his powerful strike go narrowly over the crossbar.
But Vienna completed a 4-1 success in injury time, when the brilliant Hosiner crossed for substitute Kienast to fire home.