A reentrancy attack exploits the vulnerability in smart contracts when a function makes an external call to another contract before updating its own state. This allows the external contract, possibly malicious, to reenter the original function and repeat certain actions, like withdrawals, using the same state. Through such attacks, an attacker can possibly drain all the funds from a contract.
function splitDAO(uint _proposalID, address _newCurator) noEther onlyTokenholders returns (bool _success) {
...
uint fundsToBeMoved = (balances[msg.sender] * p.splitData[0].splitBalance) / p.splitData[0].totalSupply;
//Since the balance is never updated the attacker can pass this modifier several times
if (p.splitData[0].newDAO.createTokenProxy.value(fundsToBeMoved)(msg.sender) == false) throw;
...
// Burn DAO Tokens
// Funds are transferred before the balance is updated
Transfer(msg.sender, 0, balances[msg.sender]);
withdrawRewardFor(msg.sender); // be nice, and get his rewards
// Only now after the funds are transferred is the balance updated
totalSupply -= balances[msg.sender];
paidOut[msg.sender] = 0;
return true;
}