Kevin-Prince Boateng gave Milan the lead in controversial circumstances in the 57th minute. Cristian Zapata appeared to handle Riccardo Montolivo's assist in the buildup.
Barcelona players protested but to no avail and Gerard Pique was booked in the process.
Sulley Muntari sealed the win nine minutes from time with a well-worked goal.
Milan contained Barcelona's potent attack impressively, allowing it just two shots on target all match.
Lionel Messi, kept quiet by Milan, had two late chances from free kicks and sent both shots well over the crossbar.
The result was a massive boost to Milan's turnaround from a dreadful start to the season. Massimiliano Allegri's side was 15th in the Italian league after eight games but has risen to third.
It still went into the home match as a firm underdog against a Barcelona side which has lost only twice all season in the league and in Europe.
"I think it was a great game," Allegri said. "The lads deserved this win. We didn't concede anything in defence and we had several chances. But it wasn't perfect, we were a bit lacking with the last ball in the first half but the team grew in the second. I think this is an important victory which will put us through. We could even have won 3-0, but I understand tiredness set in a bit.
"This is everyone's win, the players who played, those who didn't, the staff ... everyone."
It was Barcelona's first loss by two goals since a 3-1 defeat to Real Betis in the Spanish Cup on Jan. 19, 2011.
"It was harder than usual for us to score," Barcelona assistant coach Jordi Roura said. "Milan was very organized, very strong in defence and that caused us a lot of problems. We were also playing on a pitch that wasn't worthy of this competition. We controlled in the first half, we didn't create chances but neither did they. Then their first goal really hurt us and it was then even harder.
"If there is a team that can come back it is us. This result isn't disastrous. It's really awful to lose 2-0, really bad. But I think this squad deserves faith. We are convinced we can progress, because we are playing at home (next month), because our fans will support us, and because we're playing on our pitch, which is a pitch worthy of this competition."
While the teams knew each other well having played each other four times last season, this was a much-changed Milan side after losing experienced players such as Zlatan Ibrahimovic, Thiago Silva, Alessandro Nesta and Clarence Seedorf in the off-season.
Milan was also without Mario Balotelli, who was cup tied, and Robinho, Mathieu Flamini, Antonio Nocerino, Daniele Bonera, Luca Antonini and Nigel De Jong, who were all injured.
However, it was the Italian side which had the better opportunities in the first half and almost scored in the fifth minute when Muntari's speculative volley from outside the area sailed narrowly over the crossbar.
Stephen El Shaarawy had a chance when he cut inside the right side of the area but Barcelona captain Carles Puyol tackled him as he was about to unleash a shot. From the resulting corner Boateng curled an effort just past the far post. Giampaolo Pazzini was a whisker away from connecting with what would have been a header into an empty net.
El Shaarawy won a free kick 10 minutes after the break when he was brought down by Dani Alves. It was squared to Montolivo, whose effort appeared to be handled by Zapata as it fell to Boateng, who swivelled and fired it into the bottom right corner.
Milan doubled its lead in the 81st. Substitute M'Baye Niang's cross was flicked on by El Shaarawy to Muntari, who found himself in acres of space to volley past Victor Valdes.
Barca almost scored a valuable away goal late on, but Puyol headed a corner just wide of the left upright much to the satisfaction of spectator Novak Djokovic, the tennis star who is a fervent Milan fan.Suggest a correction