Fausto Carmona (7-15) allowed three runs on seven hits and two walks through six full frames in Cleveland's fourth win in its last five games.
"[Carmona] did a nice job of battling the whole time. You have to give him credit," Indians manager Manny Acta said. "He battled hard for the win and our bullpen was lights out."
Chris Perez tossed a 1-2-3 ninth inning to earn his 35th save of the year.
Gavin Floyd (12-12) lasted 6 2/3 innings, allowing four runs on seven hits while striking out seven. He did not walk a batter.
Adam Dunn doubled twice and knocked in a run as Chicago lost for the 10th time in 13 games.
"I just want to go up and have good at-bats. My year is what it is," said Dunn, who entered the game hitting a career-low .165.
Cleveland struck early on Hafner's two-run home run into the right-field bleachers in the first. Jason Kipnis reached base on a bunt single two batters prior to Hafner's 12th homer of the year.
After back-to-back singles by A.J. Pierzynski and Alex Rios to start the second, Dunn slapped a double down the right-field line, scoring Pierzynski. Alejandro De Aza followed with a base hit to right to bring home Rios and put runners on the corners.
De Aza was then doubled off at first when he wandered too far off the bag on Brent Morel's fly out to right field and Gordon Beckham grounded out to short to keep the game tied at two.
Cabrera broke the tie in the fourth with a leadoff home run just over the right-field wall. With the solo shot, Cabrera tied Jhonny Peralta for the Indians' franchise record for home runs in a season for a short stop with 24.
Fukudome added a solo home run in the fifth inning to increase the Indians' lead.
Rios hit a one-out single in the sixth, advanced to third on a Dunn double and crossed the plate on De Aza's groundout to second to make it a 4-3 game.
Cleveland has hit a home run in 10 of its last 11 games...The Indians have recorded an error in seven straight games...Chicago has an extra-base hit in a season-high 35 straight games...Carmona had dropped his last three decisions entering the game...Cleveland snapped a five-game losing streak at home and are 40-34 at Progressive Field this season.