The manual payout option for mmcfe has a bug that could allow an attacker to make multiple submissions to it in a very short
amount of time. The current code might allow multiple payouts. Here is my fix.
I assume you are running your payout.php script from cron every 60 seconds.
Create a new column in accountBalance called Being_Paid_Flag . Make it an INT and verify it defaults to 0. It should.
Make a copy of your original accountdetails.php for a backup.
Edit the file and and look for this chunk of code:
if($isValidAddress){
//Subtract TX feee
$currentBalance = $currentBalance - 0.1;
//Send money//
if($bitcoinController->sendtoaddress($paymentAddress, $currentBalance)) {
$paid = 0;
$result = mysql_query("SELECT IFNULL(paid,'0') as paid FROM accountBalance WHERE userId=".$userId);
if ($resultrow = mysql_fetch_object($result)) $paid = $resultrow->paid + $currentBalance;
//Reduce balance amount to zero & make a ledger entry
mysql_query("UPDATE `accountBalance` SET balance = '0', paid = '".$paid."' WHERE `userId` = '".$userId."'");
mysql_query("INSERT INTO ledger (userId, transType, amount, sendAddress) ".
" VALUES ".
"('$userId', 'Debit_MP', '$currentBalance', '$paymentAddress')");
$goodMessage = "You have successfully sent ".$currentBalance." to the following address:".$paymentAddress;
//Set new variables so it appears on the page flawlessly
$currentBalance = 0;
}else{
$returnError = "Commodity failed to send.";
}
}else{
$returnError = "That isn't a valid Bitcoin address";
Change that chunk of code to look like this:
if($isValidAddress){
mysql_query("UPDATE `accountBalance` SET Being_Paid_Flag = '1' WHERE `userId` = '".$userId."'");
$goodMessage = "You have successfully sent " .$currentBalance. " to the following address: " .$paymentAddress. " Processing in less then 60 seconds";
}else{
$returnError = "That isn't a valid Bitcoin address";
Next, find your cronjob script called payout.php. Make a backup copy of it.
Add this to the bottom of the file:
// Pay users who have Being_Paid_Flag set to 1 in accountBalance then set back to 0 when processing is done //
$resultZ = mysql_query("SELECT userId, balance, IFNULL(paid, 0) as paid, IFNULL(sendAddress,'') as sendAddress, Being_Paid_Flag FROM accountBalance WHERE Being_Paid_Flag = 1");
while ($resultR = mysql_fetch_object($resultZ)) {
$currentBalance = $resultR->balance;
$paid = $resultR->paid;
$paymentAddress = $resultR->sendAddress;
$userId = $resultR->userId;
if ($paymentAddress != '')
{
$isValidAddress = $bitcoinController->validateaddress($paymentAddress);
if($isValidAddress){
// Subtract TX fee & calculate total amount the pool will pay
$currentBalance = $currentBalance - 0.1;
$tot_paid = $resultR->paid + $currentBalance;
// Send the BTC!
// debug
// echo "sending: ". $currentBalance . " to ". $paymentAddress;
if($bitcoinController->sendtoaddress($paymentAddress, $currentBalance)) {
// Reduce balance amount to zero, update total paid amount, and make a ledger entry
mysql_query("UPDATE `accountBalance` SET balance = '0', paid = '".$tot_paid."' WHERE `userId` = '".$userId."'");
mysql_query("INSERT INTO ledger (userId, transType, amount, sendAddress) ".
" VALUES ".
"('$userId', 'Debit_MP', '$currentBalance', '$paymentAddress')");
mysql_query("UPDATE `accountBalance` SET Being_Paid_Flag = '0' WHERE `userId` = '".$userId."'");
}
}
}
}
Any final cosmetic tweaks to the website explaining this new way of doing things to users.
For example in accountdetails.php you might want to have this text blurb under "CASH OUT" to appear for users to read:
"Minimum withdrawl is 0.50 LTC. Manual payments are processed in less then 60 seconds. Please note: a 0.1 ltc transaction will apply when processing "On-Demand" manual payments"
Tweak if for your needs.
What this does for you is this: When a person tries to do multiple submissions for a manual payout all they are doing is setting the
Being_Paid_Flag to 1. That is all they can do.
When the payout.php script runs it will actually do the payout. This will defeat the attack and is probably the best way to solve
this since http/php is stateless.
If anyone sees a mistake or a way to improve this please post here.
If anyone wishes to throw me a LTC tip: LSLTFCpFX1V3offArHtvEGwtUKVs1H9zCJ