Responsibly hacking my login

reeseycup
9 years ago

0

Hey - just made a login that I wanted to see if anyone would RESPONSIBLY try and hack. It doesn’t have anything terribly sensitive at all, but deleting the database/dropping the table would be annoying.

Does anyone here want practice?

25replies
8voices
297views
nakee
9 years ago

0

@reeseycup can you prove it’s your site?

reeseycup
9 years ago | edited 9 years ago

0

@nakee
Very good question. I suppose the easiest is an e-mail from my host regarding my account with them? Is this sufficient?
http://i57.tinypic.com/rb9j5f.png

You can also see I have PHPmyadmin up for my website as well if you look at the browser tabs

The URL I will give you is on codefundamentals.com

If this is not sufficient then please let me know what proof is necessary and I will provide it :) .

I could upload a file and modify it with any sort of text you would like (confirming I have access.)

dalfor
9 years ago

0

There may be users out there that disagree with me, but I would not do it even if you had digitally verifiable copies that the site was yours. The risks of things going wrong unintentionally are just too great.

Having said that, why not go through some of the tutorials and see if you can exploit your own site as a learning tool?

reeseycup
9 years ago

0

Well as I said the worst that could happen is my site getting DDOS’d (noobie here). I don’t have anything sensitive at all in my database that I couldn’t easily restore.

The thing is, I don’t think basic hacking would work on this login. I use PHP. I filter validate the input, sanitize it, then use PDO prepared statements as well when it comes to inserting.

I have a separate table from users that tracks attempts and limits each IP attempt per second / max attempt you and lock you out.

I used to be a member here years ago but I don’t think any of the basics will work. I’m not sure how to crash test it besides letting responsible hackers take a swing at it.

Mr. Cyph3r [MrCyph3r]
9 years ago

0

I’m sure you’ll find someone glad to help you with that.

In my opinion, it would be a good thing to share the relevant portion of the code (or the whole code as you prefer) so that even people concerned about responsibility can take a look at it and give you tips and suggestions.

reeseycup
9 years ago | edited 9 years ago

0

Thank you. This is the entire class. Upon submitting the form, I filter input validate the information, and then pass it along to my checkCredentials function.
```
<?php
class UserServices
{
private $pdo;
private $error;

public function __construct(PDO $pdo)
{
$this->pdo=$pdo;
}
public function checkCredentials($email,$pass,$remember)
{
if($this->delayLogin())
{
$username=filter_var($email,FILTER_SANITIZE_EMAIL);
$password=filter_var($pass,FILTER_SANITIZE_STRING);
$remember=filter_var($remember,FILTER_VALIDATE_BOOLEAN);

  $findUser=$this->pdo->prepare("SELECT * FROM Users WHERE username=:username");  
  $findUser->execute(array(":username" => $username));  

  if($findUser->rowCount()===0)  
  {  
    $error="username";  
    return array(false,$error);  
  }  
  $userDetails=$findUser->fetch(PDO::FETCH_ASSOC);  
  if(password_verify($password,$userDetails["password"]))  
  {  
    if($remember)  
      $this->setCookie($userDetails);  

    $this->setSessions($userDetails,$this->findIP());  
    return array(true,"");  
  }  
  else  
  {  
    $error="password";  
    return array(false,$error);  
  }  
}  
else  
{  
  $error="attempts";  
  return array(false,$error);  
}  

}
private function delayLogin()
{
$grabIPuser=$this->pdo->prepare(“SELECT * FROM Attempted_Logins WHERE ip_address = :ip_address”);
$grabIPuser->execute(array(“:ip_address” => $this->findIP()));
$ipUserDetails=$grabIPuser->fetch(PDO::FETCH_ASSOC);
if($grabIPuser->rowCount()===0)
{
$insertIPdetails=$this->pdo->prepare(“INSERT INTO Attempted_Logins (ip_address,login_attempts,last_login_time) VALUES(:ip_address,:login_attempts,:last_login_time)”);
$insertIPdetails->execute(array(“:ip_address” => $this->findIP(),“:login_attempts” => 0,“:last_login_time” => $this->getDateTime(“now”,“Y-m-d H:i:s”)));
return true;
}
else
{
$dbLastAttempt=$ipUserDetails[“last_login_time”];
$lastTimeAttempt=$this->getDateTime($dbLastAttempt,false);

  $timeDiff=$lastTimeAttempt->diff($this->getDateTime("now",false));  
  if($timeDiff->format("%s")>2)  
  {  
    if($this->maxAttempts($ipUserDetails,$timeDiff->format("%i")))  
      return true;  
    else  
      return false;  
  }  
  else  
    return false;  
}  

}
private function maxAttempts($dbIpUser,$resetMinutes)
{
if($dbIpUser[“login_attempts”]<5)
{
$updateAttempts=$this->pdo->prepare(“UPDATE Attempted_Logins SET login_attempts=:login_attempts WHERE ip_address=:ip_address”);
$updateAttempts->execute(array(“:ip_address” => $dbIpUser[“ip_address”],“:login_attempts” => $dbIpUser[“login_attempts”]+1));
return true;
}
else
{
if($resetMinutes>=15)
{
$updateAttempts=$this->pdo->prepare(“UPDATE Attempted_Logins SET login_attempts=0,last_login_time=:last_login_time WHERE ip_address=:ip_address”);
$updateAttempts->execute(array(“:ip_address” => $dbIpUser[“ip_address”],“:last_login_time” => $this->getDateTime(“now”,“Y-m-d H:i:s”)));
return true;
}
else
{
$updateAttempts=$this->pdo->prepare(“UPDATE Attempted_Logins SET login_attempts=:login_attempts WHERE ip_address=:ip_address”);
$updateAttempts->execute(array(“:ip_address” => $dbIpUser[“ip_address”],“:login_attempts” => $dbIpUser[“login_attempts”]+1));
return false;
}
}
}
private function setCookie($userInfo)
{
setcookie(“rememberMe”,$userInfo[“authkey”],time() + (86400 * 14),“/”);
}
public function userCookies($loginCookie,$action)
{
$cookieUser=$this->pdo->prepare(“SELECT * FROM Users WHERE authkey=:authkey”);
$cookieUser->execute(array(“:authkey” => $loginCookie));

if($cookieUser->rowCount()===0)  
  return false;  
else  
{  
  $cookieUserInfo=$cookieUser->fetch(PDO::FETCH_ASSOC);  
  if($action==="compare")  
    return $cookieUser["authkey"];  
  else if($action==="set")  
    $this->setSessions($cookieUser,$this->findIP());  
  else  
    return null;  
}  

}
private function setSessions($userDBinfo,$thisIP)
{
$SESSION[“loggedin”]=true;
$
SESSION[“username”]=$userDBinfo[“username”];
$SESSION[“userID”]=$userDBinfo[“id”];
$
SESSION[“firstname”]=$userDBinfo[“firstname”];

$resetAttempts=$this->pdo->prepare("UPDATE Attempted_Logins SET login_attempts=0,last_login_time=:last_login_time WHERE ip_address=:ip_address");  
$resetAttempts->execute(array(":ip_address" => $thisIP,":last_login_time" => $this->getDateTime("now","Y-m-d H:i:s")));  

}
private function getDateTime($when,$format)
{
$instance=new DateTime($when);
if($format)
return $instance->format($format);
else
return $instance;
}
private function findIP()
{
return getenv(“HTTP_CLIENT_IP”)?:
getenv(“HTTP_X_FORWARDED_FOR”)?:
getenv(“HTTP_X_FORWARDED”)?:
getenv(“HTTP_FORWARDED_FOR”)?:
getenv(“HTTP_FORWARDED”)?:
getenv(“REMOTE_ADDR”);
}
}
?>```

Mr. Cyph3r [MrCyph3r]
9 years ago

0

Omg man, this is not the best way to share code… lol indentation is ugly :s

I would say to wrap it between code tags, at least…

reeseycup
9 years ago

0

I looked for a code button tag on the WYSIWYG but didn’t see it. Didn’t realize this forum used BBCODE.

I updated my above post.

Mr. Cyph3r [MrCyph3r]
9 years ago

0

It’s cool man :)

Mr. Cyph3r [MrCyph3r]
9 years ago

0

Well, the first thing I notice is in the first few lines of code…

$password=filter_var($pass,FILTER_SANITIZE_STRING);

There is no need to sanitize passwords, in fact the more complex and “ugly” they are, the better it is…. not to mention that you will hash them anyway.

reeseycup
9 years ago

0

Hmm, yeah actually that’s a good point. I don’t have a register page right now so technically doing this could potentially make some people unable to sign in.

Thanks! Would have never spotted that.

Mr. Cyph3r [MrCyph3r]
9 years ago

0

No problem man, I’ll check the rest later…

dloser
9 years ago

0

The authkey is always a risk, especially when you don’t invalidate it on login/logout. Making the cookie http-only would be a good idea as well.

The attempt limit is easily avoided because findIP uses client-supplied data. This data is also not validated in any way, which could cause problems elsewhere if you expect actual IPs in the database. (And why use getenv there?)

As a side note, I think the naming of many functions is counterintuitive. E.g., delayLogin doesn’t delay anything and actually gives true when login shouldn’t be “delayed”.

reeseycup
9 years ago

0

On logout the cookie will be destroyed and I’ll be creating a new authkey to replace there. Logging in will keep the authkey until it expires or it logs out.

As far as findIP(), that uses code I found online which said it was reliable to correctly find the IP of the user. If you think you can get a better IP, please let me know how I can do that. That whole return data is based off code I found online.

I’ll go over naming more also - I touched it up but I guess I need to revisit it more.

dloser
9 years ago

0

The only reliable IP is in REMOTE_ADDR. The rest are headers supplied by the client and thus unreliable. Downside is that REMOTE_ADDR might be a proxy that is used by multiple users, but with a decent atttempt limit and timeout that needn’t be a problem, I think.

reeseycup
9 years ago | edited 9 years ago

0

Yeah I read about the proxy by multiple users and there was a stackoverflow thread where they advocated that method in my code to see which IP would be best.

Ultimately it doesn’t matter too much because the goal is to just delay them logging in repeatedly. As long as I grab some sort of identifiable information (fake iP or not) then that’s fine. They’ll still need to delay and get another IP if they want to continue which still will slow them down.

If more people agree that I should change it to REMOTE_ADDR then I will happily do so :).

My code does feature a 2s delay between attempts and a 5 max attempt so user-submitted code won’t even touch my Users table unless they are slow enough / under 5 attempts (or over 15 minutes in which case it’ll reset the 5 attempt rule).

I’m not seeing TOO much criticism so I’m guessing it’s not the worst code that you all have seen before. It’s somewhat reassuring. First PHP class I’ve ever made. Proud of my baby.

dloser
9 years ago

0

The point is that they don’t have to get another IP. You can just attempt to log in as fast as your connection allows by setting the right header to a different value every time. Doesn’t even have to be an IP. I can write a simple script to do this in about a minute or so.

reeseycup
9 years ago

0

Gotcha. That does make sense. Ok I just changed it :) .

dloser
9 years ago

0

One of the most important things you do in your code is using prepared statements. With that, it’s a lot harder to screw up big time.

reeseycup
9 years ago

0

Do you see any big flaws I have though? I’d be happy to open up the test page to you all (I can verify using whatever the standard way is).

dloser
9 years ago

0

Not seeing them doesn’t mean they aren’t there… ;)

reeseycup
9 years ago

0

Oh I know that’s why I came to the experts :P (or at least much smarter than myself.)

Mr. Cyph3r [MrCyph3r]
9 years ago

0

Well, it looks like you have received a lot of really useful tips… nice :)

NITIN PAL [wiltoriya]
9 years ago

0

hakcking account activated

joebuzz
9 years ago

0

Hey I’m a beginer and I’m only ten so could I try

Reply has been removed
You must be logged in to reply to this discussion. Login
1 of 26

This site only uses cookies that are essential for the functionality of this website. Cookies are not used for tracking or marketing purposes.

By using our site, you acknowledge that you have read and understand our Privacy Policy, and Terms of Service.

Dismiss