Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I've been practicing security-related subjects and this challenge has befuddled me. Note: I can't access any PHP source code, nor can I edit it. I'm only able to view it.
The following is given:
I have two inputs, "user" and "pass"
After 30 times the form is sent, the salt, the hashes and the final solution change. So bruteforce isn't an option (sadly!)
#The bottom of the page (not shown in the code for some reason), it echos that it found 9 users (calling the getnumberofusers() function)
I've managed to extract this:
username = root
hashed password = 551e18b35e17017742a8ce4ed27f626e
Token (possibly salt?) = 0St31ez14wOT6jTh
What I've attempted thus far with unsuccessful results:
Using SQL injection, select a known MD5 collision as password and send its counterpart as "pass", however the salt is bothering this process. Clearly I couldn't bruteforce this because after 30 attempts the salt would change.
I tried finding the entire list of users but it doesn't print the output anywhere (only errors)
This is the code we receive:
<?php
//by Mawekl
//Objective: login as root.
//Objective is NOT:
// - Blind SQLI
// - Bruteforce password/salt/id
#WARNING
#ANTI-BLIND
#for every 30 queries
#all hashes, salt
#and final solution
#will be reset.
function getnumberofusers()
{
$q = "SELECT 1 FROM `sqlinjection1`";
$r = mysql_query($q);
return 'Number of users: ' . mysql_num_rows($r);
}
function getinfo($user)
{
$q = "SELECT `id`, `password` FROM `sqlinjection1` WHERE `username`='$user'";
$r = mysql_query($q);
if(!$r)
return mysql_error();
$r = mysql_fetch_array($r);
if(!$r)
return "Username doesn't exists.";
return $r;
}
function getfullinfo($id)
{
$q = "SELECT * FROM `sqlinjection1` WHERE `id`=$id";
$r = mysql_query($q);
if(!$r)
return mysql_error();
$r = mysql_fetch_array($r);
if(!$r)
return "What the hell?!";
return $r;
}
function confirmpassword($pass, $passcorrect, $salt)
{
$pass = md5(md5(md5($pass)).$salt);
return $pass===$passcorrect;
}
function challenge($user, $pass)
{
$info = getinfo($user);
if(!is_array($info))
return $info;
$confirm = confirmpassword($pass, $info['password'], $_ENV['ST_SALT']);
if(!$confirm)
return 'Wrong password!';
$info = getfullinfo($info['id']);
if(!is_array($info))
return $info;
$returnmessage = "Welcome " . $info['username'] . "!" . PHP_EOL .
$info['welcomemessage'] . PHP_EOL;
return $returnmessage;
}
?>
Any help is appreciated, and if you have any questions I'd love to clarify my question!
now we can select the welcome message/anything else using sql
$user="1' or exp(~(select * from (select welcomemessage from sqlinjection1 where username='user1')a)) or '1'='1"
but when we found a Secret token (that i wrote up there ^) hidden in the data base and tried using it this way:
The idea: select the hashed version as password using SQL injection so the hashes match.
Here's the code:
<?php
$salt = "v5IftFb0Tx1Jhp4b";
$hashed = "";
$p = "hello";
$hashed = md5(md5(md5($p)).$salt);
echo "The Query: " . "' AND 1 = 0 UNION SELECT `id`, '$hashed' AS `password` FROM sqlinjection1 WHERE `username` = 'root';#";
?>
It echoes the query which we put in the "username" field. In the "password" field we enter "hello".
However it's not working...
but it did not work, anyone has any idea what else can we do? How can we find out what / modify the $_ENV["ST_SALT"]? as appearently its not the secret token that we found
Related
This question already has answers here:
Insert data only if record does not exist
(3 answers)
Closed 9 years ago.
I need to have a system where a random password and username are created for each new user.
As such, I need to make sure the username is unique.
However I cant figure out why the code below isn't working. It isn't a syntax issue. I just can't figure out where I have gone wrong logically.
anyway here is what I have tried:
$Password= randomPassword();
$Username = randomPassword();
$UsernameCheckQuery = mysql_query("SELECT * FROM users WHERE username = '".$Username."'");
while (mysql_num_rows($UsernameCheckQuery ) >= 1) {
$Username = randomPassword();
$UsernameCheckQuery = mysql_query("SELECT * FROM users WHERE username = '".$Username."'");
}
I know this topic appears elsewhere on Stack Overflow and on the web. However every question I have seen has been using an if statement to check if the username is already used. In my case I cant see how an if statement would work as the randomPassword function could generated two username that already exist in a row.
Try
while (true) {
$Username = randomPassword();
$UsernameCheckQuery = mysql_query("SELECT * FROM users WHERE username = '".$Username."'");
if (mysql_num_rows($UsernameCheckQuery ) < 1) {
break;
}
}
echo 'The generated username is '.$Username;
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
So I have a php authentication script and everything works fine. But I'm very unsure about the way I programmed it (I hardcoded some stuff) and I was hoping stack could look through this and point out any potential problems.
Here is the script:
<?php
require_once 'Bcrypt.php';
class Mysql {
private $conn;
function __construct() {
$this->conn = new PDO('mysql:host=***;dbname=***;charset=UTF-8','***','***') or
die('There was a problem connecting to the database.');
}
function verify_Username_and_Pass($un, $pwd) {
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);
$query = "SELECT *
FROM Conference
WHERE Username = :un";
$stmt = $this->conn->prepare($query);
$stmt->bindParam(':un', $un);
//$stmt->bindParam(':pwd', $pwd);
$stmt->execute();
$row = $stmt->fetchAll();
$hash = $row[0]["Password"];
$is_correct = Bcrypt::check($pwd, $hash);
if ($is_correct) {
// User exist
$firstName = $row[0]["First Name"];
$_SESSION["FirstName"] = $firstName;
return true;
$stmt->close();
}
else {
// User doesn't exist
return false;
$stmt->close();
}
}
}
?>
So how does it look?
Without testing it out, i think your code should work, the usage of BCrypt looks reasonable. There are some points that could be improved of course, some are maybe a matter of opinion.
If your query doesn't return any row (because no such user name exists), you would access an invalid index $row[0]["Password"]. You should first ask, if there is a result, before using it.
Your call for closing the database is placed after the return statement, so it will never be executed. PHP will close the database automatically, so either close it before the return statement, or remove the line.
You named your function verify_username_and_password(), but actually it does also read from the database and writes to the session. These are hidden activities, another developer cannot know that the session changes unless he reads the whole code. One possibility to solve this problem would be, to split up the function.
untested example:
$userRow = getUserRowFromDatabase($userName);
if (!is_null($userRow))
{
if (verifyPassword($password, $userRow["Password"]))
{
addLoggedInUserToSession($userRow["First Name"])
}
}
Each of these three functions have only one problem to solve. This would make your code more readable, ideally it should be like reading a story in a book.
Hope i could give you some ideas.
You can actually use mysql to verify the hash for you
SELECT COUNT(*) FROM Conference
WHERE Username = :un
AND Password = ENCRYPT(:pass, Password)
LIMIT 1
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
i have this information on my database...
Username - kam, mav, shin
Password - kam, mav, shin
this is my code...
<?php
$con=mysql_connect("localhost","root","");
mysql_select_db("nnx",$con);
$tbl2=mysql_query("SELECT * FROM tablename WHERE `username` =
'".mysql_real_escape_string($_POST['username'])."' and `password` =
'".mysql_real_escape_string($_POST['password'])."'");
while($row=mysql_fetch_array($tbl2))
if (($row['username']==$_POST['username'])&&($row['password']==$_POST['password']))
{
echo " ";
}
if (($row['username']!=$_POST['username'])&&($row['password']!=$_POST['password']))
{
header("location: /login.php?codeError=1");
die;
}
?>
the problem is, if i enter the username "mav" and the password is "kam", it still go through the next page. What should i do?
You should just check if the query returns any rows with mysql_num_rows():
$con=mysql_connect("localhost","root","");
mysql_select_db("nnx",$con);
$tbl2 = mysql_query("SELECT `username`, `password` FROM `tablename` WHERE
`username` = '".mysql_real_escape_string($_POST['username'])."' AND
`password` = '".mysql_real_escape_string($_POST['password'])."'
");
$rows = mysql_num_rows($tbl2);
if($rows){
// user and password exists in db
} else {
// does not exist
header("location: /login.php?codeError=1");
die;
}
Like I told you in previous question, try to move from mysql_* functions.
Just a suggestion but why not try it this way:
if (($row['username']==$_POST['username'])&&($row['password']==$_POST['password']))
{
echo " ";
}else{
header("location: /login.php?codeError=1");
die;
}
I don't understand why you need two if statements here, it's only boolean and the result will either be true or false.
Hope this helps :)!
You are checking for validation already in your query. If the user entered username and password correctly and only then, the query returns a row, containing that data.
So you only have to count the rows returned bye your Query. If it is below 1, then the user is not authenticated
Try
if (($row['username']==$_POST['username'])&&($row['password']==$_POST['password']))
{
echo " ";
}
else
{
header("location: /login.php?codeError=1");
die();
}
Anyway, a nice way to address this kind of issues is temporary printing on screen the variables (as a debug).
echo $row['username']." ".$_POST['username']." ".$row['password']." ".$_POST['password']
see if the variables are actually there of if there are issues with your DB query or with the form that posts the data.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Why isn't this code working?
$welcome = mysql_query("SELECT welcome FROM users WHERE id = '" . $_SESSION['user']['id'] . "'");
if($welcome == '0')
{
echo 'register is 0';
}
else
{
echo 'register is 1';
}
$_SESSION['user']['id'] returns as 1, by the way.
MySQL returns a resource on success, false on error, not a value from the query. Try this:
$welcome = mysql_query("SELECT welcome FROM users WHERE id = '" . $_SESSION['user']['id'] . "'");
$row = mysql_fetch_assoc($welcome);
if($row['welcome']== '0')
{
echo 'register is 0';
}
else
{
echo 'register is 1';
}
You shouldn't build your query like that as you'll not be protected from a SQL Injection Attack.
$query = sprintf("SELECT welcome FROM users WHERE id = %d", $_SESSION['user']['id']);
// Perform Query
$result = mysql_query($query);
Once that has finished you then need to fetch from the result, you cannot just query it.
if(!$result)
echo "Error"; // Deal with it
$row = mysql_fetch_assoc($result);
echo $row['welcome'];
mysql_free_result($result);
According to MySQL documentation, the resource is returned if the select statement is successful, or 'false' if the statement fails.
Although there's a better, more secure way to achieve what you are trying to accomplish, your statement can be revised simply to :
if($welcome === false)
{
echo 'register is 0';
}
else
{
echo 'register is 1';
}
That will work, but as I said earlier, the whole code needs to be updated to a more secure version.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I was wondering what could of allowed a user to hack my site, they changed my username, personal info and password. Can someone give me some suggestions on what it could have been. I'm using PHP MySQL and HTMLPURIFIER.
Here is the login script.
<?php
if (isset($_POST['submitted'])) { // start of submit conditional.
require_once (MYSQL);
// Validate the username or email address:
if (!empty($_POST['login']) && strlen($_POST['login']) <= 255) {
$e = mysqli_real_escape_string($dbc, $purifier->purify(strip_tags($_POST['login'])));
} else if(!empty($_POST['login']) && strlen($_POST['login']) >= 256) {
$e = FALSE;
echo '<p>Your username or email address cannot exceed 255 characters!</p>';
} else {
$e = FALSE;
echo '<p>You forgot to enter your username or email address!</p>';
}
// Validate the password:
if (!empty($_POST['pass']) && strlen($_POST['pass']) <= 255) {
$p = mysqli_real_escape_string($dbc, $_POST['pass']);
} else if(!empty($_POST['pass']) && strlen($_POST['pass']) >= 256) {
$p = FALSE;
echo '<p>Your password cannot exceed 255 characters!</p>';
} else {
$p = FALSE;
echo '<p>You forgot to enter your password!</p>';
}
if(($e != FALSE) && ($p != FALSE)) { // check pass
$pass_salt = "SELECT users.password, users.salt FROM users JOIN contact_info ON contact_info.user_id = users.user_id WHERE (contact_info.email = '" . $e . "' OR users.username = '" . $e . "') AND users.active IS NULL";
$ph = mysqli_query($dbc, $pass_salt) or trigger_error("Query: $pass_salt\n<br />MySQL Error: " . mysqli_error($dbc));
while($row = mysqli_fetch_array($ph)){
$password = $row['password'];
$salt = $row['salt'];
}
if(!empty($salt)) {
$sha512 = hash('sha512', $p . $salt);
}
if(!empty($password) == !empty($sha512)){
$user_pass = TRUE;
} else {
$user_pass = FALSE;
}
}
if(isset($user_pass) && ($user_pass == TRUE) && !empty($salt)) { // If everything's OK.
// Query the database:
$q = "SELECT users.user_id, users.first_name, users.user_level FROM users JOIN contact_info ON contact_info.user_id = users.user_id WHERE (contact_info.email = '" . $e . "' OR users.username = '" . $e . "') AND users.password = '" . $sha512 . "' AND users.active IS NULL";
$r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (#mysqli_num_rows($r) == 1) { // A match was made.
// Register the values & redirect:
$_SESSION = mysqli_fetch_array ($r, MYSQLI_ASSOC);
// check if user is logged in then update the old login date
$u = "UPDATE users JOIN contact_info ON contact_info.user_id = users.user_id SET users.last_login = NOW(), users.deletion = 0, users.deletion_date = NULL WHERE (contact_info.email = '" . $e . "' OR users.username = '" . $e . "') AND users.password = '" . $sha512 . "' AND users.active IS NULL";
// save the info to the database
$r = mysqli_query ($dbc, $u);
mysqli_free_result($r);
mysqli_close($dbc);
$url = BASE_URL . 'home/index.php'; // Define the URL:
header("Location: $url");
exit(); // Quit the script.
} else { // No match was made.
echo '<p>Either your username, email address or password entered do not match those on file or you have not yet activated your account.</p>';
}
} else { // If everything wasn't OK.
echo '<p>Please try again.</p>';
}
mysqli_close($dbc);
} // end of submit conditional.
?>
You should be aware of SQL Injection. That is what came up to my mind first (noticing the use of MySql). To prevent this you have to sanitize users input by using mysql_real_escape_string() (different mysql_escape_string() which is considered as deprecated). Despite this solution I'd suggest you to use either PDO or Mysqli (I usually discourage this one) in order to just fix the SQL Injection problem by the usage of Prepared Statements.
Then you should be probably aware of XSS (cross-site-scripting) that could have "injected" in your code some sort of malicious Javascript script. You can fix this a little with htmlspecialchars() that make HTML tags (such as <script>) not considered as HTML tags.
Also take a look at this Vulnerability list for PHP.
P.S.
In order to make your code more readable and "right" I'd suggest you to change strlen($_POST['login']) >= 256 into strlen($_POST['login']) > 255 which is the same but makes the reader understand immediately that the real limit is not 256 but 255.
First, make sure they can't perform an SQL injection. This is probably what they did. This is normally caused from input fields that are executed. The person doing it just has to type in an SQL command.
You can see details on this here.
Oh, welcome to StackOverflow.com! I hope you enjoy the site!
In addition to the DalexL answer, please check that you have a strong password to connect to your database.
I'm pretty sure this didn't happen to the original poster, but deceptive companies have been known to send "bills" to companies with web sites. The fine print in the "bills" transferred the domain from the company to the deceptive company.
Here's one example: Domain Registry of America scam
If you allow users to upload images, you may have been a victim of a GIF exploit. If your server settings aren't secure, viewing a GIF with embedded PHP code in it will execute the code. Check if you can find any .gif.php (or .php.gif) files on your system, they may still be there if the hacker forgot to clean up after himself.
If HTMLPURIFIER is implemented correctly for all db facing inputs then you should evaluate how you are transmitting your logins. Are you pre-hashing before submit on the client side.
I would assume that the reason is there is an input on a form that is unfiltered and it is letting some SQL injected code through.