The visitors opened the scoring through Humberto Suazo's 11th-minute penalty and, despite having Jesus Zavala dismissed 10 minutes later, they looked well in control when Roberto Juarez put through his own goal just before the hour mark.
However Puebla stormed back and two goals from substitute Isaac Romo, sandwiching one from Juarez, had them on the brink of victory.
However, Luis Perez held his nerve to convert a last minute penalty and prevent Puebla moving into the top half.
Atlante climbed three places with a 1-0 win at fellow strugglers Club America, courtesy of Osvaldo Martinez's 48th-minute goal. The hosts had Jesus Molina dismissed on the stroke of half-time.
Toluca and Tijuana drew 1-1, with substitute Jose Sand's 90th-minute goal cancelling out Ivan Alonso's 66th-minute effort for Toluca.