Jenson Button claimed victory in his 200th grand prix as he perfectly judged an absorbing race in changeable weather in Hungary.
McLaren could have had a one-two, with Lewis Hamilton leading much of the race, but a tyre strategy misjudgement and a penalty ruined Hamilton's afternoon.
World championship leader Sebastian Vettel had to settle for second, ahead of Fernando Alonso's Ferrari and the recovering Hamilton.
McLaren had taken the advantage early in a race that began on a damp track with everyone on intermediates, Hamilton attacking Vettel relentlessly through the opening laps as both slid around in a dice more reminiscent of a karting scrap than Formula 1.
The lead finally changed on lap five, when Vettel ran wide at Turn 2 and Hamilton breezed past and pulled away, soon extending a four-second lead over the championship leader, who was at least able to drop Button at this stage.
Laps 10 to 13 saw all the leaders decide the track was ready for slicks, and coming in one lap sooner than Vettel paid off for Button, who made the most of his warmer tyres and greater confidence to take second place into Turn 2.
Mark Webber pulled off the same move on Alonso for fourth at the same time. The Ferrari had lost ground through the first corner on the opening lap, then charged back up the order despite two minor trips off the road.
The relatively serene middle phase of the race saw Hamilton holding a comfortable gap over Button, who had a similar 5s advantage back to Vettel, while Webber fended off Alonso 10s behind them.
Alonso decided to make a relatively early third pitstop and take another set of super softs, while all the other leaders except Hamilton switched to the harder softs at this point.
The burst of pace on fresh Pirellis allowed Alonso to jump both Red Bulls during his rapid laps before they pitted, though the tyres then began to wear and he lost third to Vettel again.
Hamilton followed the same strategy as Alonso, which left him looking very vulnerable to Button as he looked unlikely to pull out enough of a gap to pit again for the softs, but in the event the return of the rain rendered these tactics rather irrelevant.
The sudden shower hit on lap 47, causing Hamilton to spin at the chicane. He tried to rejoin as quickly as possible, but could not prevent Button taking the lead - and also forced Paul di Resta's lapped Force India off the road as he rotated, a move that would ultimately earn Hamilton a penalty.
With the rain increasing, Button slipped up at Turn 2 four laps later, allowing Hamilton back into the lead. Button retaliated on the following lap and briefly regained first place on the pits straight, only to go wide again at Turn 2 as the top spot was exchanged yet again.
But just as Hamilton moved back into first, he made what turned out to be the costly decision to pit again for intermediates. It was obvious almost immediately that this was the wrong call, as the rain rapidly vanished, and the Briton was soon back in for slicks. His drive-through penalty for nearly wiping out di Resta soon followed, dropping him to sixth and leaving Button clear to win.
The 2009 champion briefly came under pressure from Vettel, but had the pace to pull away again and clinch his second victory of the year.
With Webber also switching to intermediates unnecessarily, Alonso regained third, which he held despite a quick late spin.
Hamilton battled back to fourth ahead of Webber, with Felipe Massa recovering from an early spin to sixth in the other Ferrari.
Kamui Kobayashi tried to go the distance on just two tyre stops and held seventh heading into the closing stages, albeit with a massive queue of cars chasing his Sauber. The plan did not work, and he had to pit for fresh rubber after tumbling down the order, as di Resta came through to seventh and Sebastien Buemi turned 23rd on the grid into an eighth place for Toro Rosso.
Mercedes only took ninth place, Nico Rosberg having also pitted for intermediates late on. Michael Schumacher had a gearbox problem shortly after spinning while dicing with Massa in the opening stages. Jaime Alguersuari (Toro Rosso) clashed with Kobayashi during their late battle but still took 10th.
Adrian Sutil (Force India) and Sergio Perez (Sauber) saw their great qualifying results wasted in a first lap incident that delayed both.
One of the most spectacular incidents of this highly eventful race befell Nick Heidfeld, whose Renault caught fire in the pit exit after a long stop, with a minor explosion on its left-hand side as the marshals dealt with the blaze.