I'm not sure this is MySQL injection from what I see, but here's the scenario.
We have a contest that runs on our site. A cousin of one of the contestants posted a link, from his browser after he'd voted, in a forum to have other people go vote for her.
The problem, however, is that he posted the url to the vote result page that still had the contestants info in it. So instead of directing people to the site for them to vote for themselves, this caused anyone who clicked the link to automatically vote for here against their will.
Now I can't go about re-writing the entire code as I didn't create it, it would take vast amounts of time for me, and we're still in the middle of the contest.
However can anyone aid me in adding something into these php files that will protect against things like this? Or is it unavoidable?
Here is the file that I think needs altering, although if this is not it, please let me know and I can gather the required info ASAP.
$queryIP = "SELECT INET_NTOA('ip') FROM ips WHERE ip=INET_ATON('$ip')";
$resultIP = mysql_query ($queryIP);
$existIP = mysql_num_rows($resultIP);
if (isset($_COOKIE['vote']) || $existIP > 0)
{
$message = "<b>You have already voted in this year's Senior Challenge!</b> <p>To view the rankings of the current Senior Challenge contestants, <a href=\"/voteresults.php\">click here</a></p>";
}
else
{
//Get Senior info
$query = "SELECT * FROM seniors WHERE sen_id=$_GET[sen_id]";
$result = mysql_query ($query);
$row = mysql_fetch_array ($result);
if(isset($resultTally))
{
$message = "<b>Your vote has been registered!</b> <p>Thank you for participating in the 2012 Senior Challenge. To view the rankings of the current Senior Challenge contestants, <a href=\"/sencha-top10.php\">click here</a></p>";
}
else
{
$message = "<b>Error: Vote was not counted!</b> <p>You have encountered an error, and your vote was NOT tallied. Please, <a href=\"/contact.html\">contact us</a> to tally your vote.</p>";
}
}
<br />
<h3>Invite people to vote!</h3>
<p>Increase <?php echo $row['first_name']?>'s chances of winning the Senior Challenge by inviting friends and family to vote!</p>
<form action ="<?PHP echo $_SERVER['PHP_SELF']; ?>?sen_id=<?php echo $row['sen_id']; ?>" method="post">
<p>E-mail address: <input name="addy" type="text" size="30" maxlength="50" ></p>
<input name="mail" type="submit" value="Send">
</form>
<?php
//Email!
if (isset($_POST['mail']))
{
if (empty($_POST['addy']))
{
$e = FALSE;
$Pmessage .= '<p>Please enter the e-mail address...</p>';
}
else if(!eregi("^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$", stripslashes(trim($_POST['addy']))))
{
$problem = FALSE;
$Pmessage .= '<p>Please enter a valid e-mail address.</p>';
}
else
$e = escape_data($_POST['addy']);
if ($e)
{
//Send an e-mail
$to = "$e";
$subject = "Vote for $row[first_name] $row[last_name] in the Ruth Olson Photography Senior Challenge!";
$message = "Hello,
$row[first_name] $row[last_name] is a contestant in the Ruth Olson Photography Senior Challenge. $row[first_name] currently has $row[votes] votes, but every new vote counts!
If you would like to vote for $row[first_name], follow the link below...
There is no 'flaw' in this (from the problem stance anyway). The problem is you're relying on the GET which has been passed as a part of the hard url. Rewrite the code to use POST instead, and it won't matter if a querystring is provided to it.
If you cannot rewrite it, you're out of luck. URL Rewriting cannot be done to fix this. If the value is stripped out of it, then it will never process it either. In either case, the code was not written properly to handle input in any way; providing it with nothing in the querystring would still attempt to update that non-existent entry.
There is no 'flaw' in this (from the problem stance anyway). The problem is you're relying on the GET which has been passed as a part of the hard url. Rewrite the code to use POST instead, and it won't matter if a querystring is provided to it.
If you cannot rewrite it, you're out of luck. URL Rewriting cannot be done to fix this. If the value is stripped out of it, then it will never process it either. In either case, the code was not written properly to handle input in any way; providing it with nothing in the querystring would still attempt to update that non-existent entry.
Is that as simple as changing get to post, or is it more complicated than that? A year later and I'm still struggling to understand what this guys did.
To make it workable, _POST would have to be used instead of _GET, the form would need to be modified to use POST instead of GET or implicit method, and the action would have to drop the querystring added and use a hidden submit field instead.
The actual processing should be modified to only deal with it if $_POST['sen_id'] isset. Although if it doesn't, it will simply throw errors (which it currently does now if now sen_id isn't provided, but must not be configured to show).
I see that there are two processing blocks though, one for voting and one for mailing. Is there a different form that's actually used prior to this one?
To make it workable, _POST would have to be used instead of _GET, the form would need to be modified to use POST instead of GET or implicit method, and the action would have to drop the querystring added and use a hidden submit field instead.
The actual processing should be modified to only deal with it if $_POST['sen_id'] isset. Although if it doesn't, it will simply throw errors (which it currently does now if now sen_id isn't provided, but must not be configured to show).
I see that there are two processing blocks though, one for voting and one for mailing. Is there a different form that's actually used prior to this one?
Yes. We have the actual voting pages which after a vote is placed, they are directed to the tally page. Code down below.
1 out of the 5 voting pages (pulls specific groups of the alphabet):
PHP Code:
<div id="sencha">
<h3>2012 Senior Challenge Contestants</h3> <br />
<p><span id="strong">Senior Challenge Leaderboard:</span> <a href="./sencha-top10.php">Click here to view the current Top 10!</a><br /><br /> To build suspense we have removed the voting counters. Keep up the voting!<br /> We allow one vote per household.</p><br />
$queryIP = "SELECT INET_NTOA('ip') FROM ips WHERE ip=INET_ATON('$ip')"; $resultIP = mysql_query ($queryIP); $existIP = mysql_num_rows($resultIP);
if (isset($_COOKIE['vote']) || $existIP > 0) { $message = "<b>You have already voted in this year's Senior Challenge!</b> <p>To view the rankings of the current Senior Challenge contestants, <a href=\"/voteresults.php\">click here</a></p>"; } else { //Get Senior info $query = "SELECT * FROM seniors WHERE sen_id=$_GET[sen_id]"; $result = mysql_query ($query); $row = mysql_fetch_array ($result);
if(isset($resultTally)) { $message = "<b>Your vote has been registered!</b> <p>Thank you for participating in the 2012 Senior Challenge. To view the rankings of the current Senior Challenge contestants, <a href=\"/sencha-top10.php\">click here</a></p>";
} else { $message = "<b>Error: Vote was not counted!</b> <p>You have encountered an error, and your vote was NOT tallied. Please, <a href=\"/contact.html\">contact us</a> to tally your vote.</p>"; } }
<br /> <h3>Invite people to vote!</h3> <p>Increase <?php echo $row['first_name']?>'s chances of winning the Senior Challenge by inviting friends and family to vote!</p> <form action ="<?PHP echo $_SERVER['PHP_SELF']; ?>?sen_id=<?php echo $row['sen_id']; ?>" method="post"> <p>E-mail address: <input name="addy" type="text" size="30" maxlength="50" ></p> <input name="mail" type="submit" value="Send"> </form>
<?php //Email!
if (isset($_POST['mail'])) { if (empty($_POST['addy'])) { $e = FALSE; $Pmessage .= '<p>Please enter the e-mail address...</p>'; }
else if(!eregi("^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$", stripslashes(trim($_POST['addy'])))) { $problem = FALSE; $Pmessage .= '<p>Please enter a valid e-mail address.</p>'; }
else $e = escape_data($_POST['addy']);
if ($e) {
//Send an e-mail $to = "$e"; $subject = "Vote for $row[first_name] $row[last_name] in the Ruth Olson Photography Senior Challenge!"; $message = "Hello,
$row[first_name] $row[last_name] is a contestant in the Ruth Olson Photography Senior Challenge. $row[first_name] currently has $row[votes] votes, but every new vote counts!
If you would like to vote for $row[first_name], follow the link below...
Then no one can manually link to or type in an id.
That what you mean Fou?
Thanks for that . I get what he's saying. It's just that since I don't know a lot about PHP coding and that guys hasn't been here for the past 2-3 years...I have no clue how to go about changing it lol. So I have no idea what exactly needs to get changed to POST and what needs to stay and what needs to be deleted.
Last edited by Psionicsin; 10-13-2011 at 07:46 PM..