I have a UITableView with 5 UITableViewCells. Each cell contains a UIButton which is set up as follows:
- (UITableView         
        To do (@Vladimir)'s answer is Swift:
var buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
var indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!
Although checking for indexPath != nil gives me the finger..."NSIndexPath is not a subtype of NSString"
It's simple; make a custom cell and take a outlet of button
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         NSString *identifier = @"identifier";
        customCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    cell.yourButton.tag = indexPath.Row;
- (void)buttonPressedAction:(id)sender
change id in above method to (UIButton *)
You can get the value that which button is being tapped by doing sender.tag.
SWIFT 2 UPDATE
Here's how to find out which button was tapped + send data to another ViewController from that button's indexPath.row as I'm assuming that's the point for most!  
@IBAction func yourButton(sender: AnyObject) {
     var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
        let indexPath = self.tableView.indexPathForRowAtPoint(position)
        let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
        UITableViewCell
        print(indexPath?.row)
        print("Tap tap tap tap")
    }
For those who are using a ViewController class and added a tableView, I'm using a ViewController instead of a TableViewController so I manually added the tableView in order to access it.
Here is the code for passing data to another VC when tapping that button and passing the cell's  indexPath.row 
@IBAction func moreInfo(sender: AnyObject) {
    let yourOtherVC = self.storyboard!.instantiateViewControllerWithIdentifier("yourOtherVC") as! YourOtherVCVIewController
    var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(position)
    let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
    UITableViewCell
    print(indexPath?.row)
    print("Button tapped")
    yourOtherVC.yourVarName = [self.otherVCVariable[indexPath!.row]]
    self.presentViewController(yourNewVC, animated: true, completion: nil)
}
I found the method of using the superview's superview to obtain a reference to the cell's indexPath worked perfectly. Thanks to iphonedevbook.com (macnsmith) for the tip link text
-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...
}
Found a nice solution to this problem elsewhere, no messing around with tags on the button:
- (void)buttonPressedAction:(id)sender {
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
    // do stuff with the indexPath...
}
In Apple's Accessory sample the following method is used:
[button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
Then in touch handler touch coordinate retrieved and index path is calculated from that coordinate:
- (void)checkButtonTapped:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     ...
    }
}