My primary programming language is python, but I inherited a PHP project to maintain, and I am trying to fix some SQL injection vulnerabilities. I have one file that has me baffled. It is working, but I have no idea how. On line 14, it invokes $db, but I do not understand how $db is available within that function. It is defined in other php files within the project, but my understanding was that global variables have to be declared (as $tbl_users is) to be available inside a function. Where else do I need to look to know where authValidateUser is getting $db from?
<?php
$user_list_link = "edit_users.php";
function authValidateUser($user, $pass)
{
global $tbl_users;
$user = strtolower($user);
$pass = md5($pass);
$user = preg_replace("/[^a-z0-9.]+/i","",$user);
$pass = preg_replace("/[^a-z0-9.]+/i","",$pass);
return sql_query1($db, "select count(*) from $tbl_users where name = '$user' and password = '$pass';");
}
function authGetUserLevel($user, $lev1_admin)
{
// User not logged in, user level '0'
if(!isset($user))
return 0;
// Check if the user is can modify
for($i = 0; isset($lev1_admin[$i]); $i++)
{
if(strcasecmp($user, $lev1_admin[$i]) == 0)
return 2;
}
// Everybody else is access level '1'
return 1;
}
?>
sql_query1 is the following:
function sql_query1 ($db, $sql)
{
$r = mysqli_query($db, $sql);
if (! $r) return -1;
if (mysqli_num_rows($r) != 1 || mysqli_num_fields($r) != 1
|| ($result = mysqli_result($r, 0, 0)) == "") $result = -1;
mysqli_free_result($r);
return $result;
}
Related
This question already has answers here:
Running a loop that has a function inside it
(9 answers)
Closed 2 years ago.
I have the below code that I am trying to fix. In this code, I have created a class and that has a function testcal() in it. In that function, I connect to database, do a select query from a table. For the result set, I want to loop through and grab values of fields $field1,2,3. Using those fields I am creating another function to throw out the result.
<?php
class test
{
public function testcal()
{
set_error_handler(function($errno, $errstr){
error_reporting(0);
}, E_WARNING);
//database credentials
$host = "localhost";
$db_name = "mydb";
$username = "root";
$password = "";
//connect to database
$con = mysqli_connect($host,$username,$password,$db_name);
//Query to generate check-in variables from ffc_contrast
$sql = "SELECT * FROM mytable";
//Store result on $result variable
$result = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($result))
{
//assign values to each variable
$field1 = $row["field1"];
$field2 = $row["field2"];
$field3 = 0.5;
////////////////
//Calculations//
////////////////
function ratingcheck($field1,$field2){
if($field1 == 0 || $field2 == 0){
return 0;
} elseif ($field1 == 1) {
return 1;
} elseif ($field2 == 2) {
return 2;
}else{
return null;
}
}
}
}
}
$test = new test();
print $test->testcal();
?>
I am getting an error saying Cannot redeclare ratingcheck() (previously declared in ~/myfile.php:51) in ~/myfile.php on line 37 I have declared the method correctly and have called the parent method. Not sure why I am getting this error. Can someone help?
class test
{
public function testcal()
{
....all your code....
//Store result on $result variable
$result = mysqli_query($con, $sql);
$returnValues = [];//not sure what you want here really, as you're returning inside youe while loop
//so that will only do 1 iteration anyway, so i'm assuming you want to build an array or something
while($row = mysqli_fetch_assoc($result))
{
//assign values to each variable
$field1 = $row["field1"];
$field2 = $row["field2"];
$field3 = 0.5;
//store the result from the function
$returnValues[] = $this->ratingcheck($field1,$field2);
}
return $returnValues;
}
////////////////
//Calculations//
////////////////
//declare the function once as part of the class, now you can call it
//i've put private here as it's making an inernal calculation, make it public if you prefer
private function ratingcheck($field1,$field2){
if($field1 == 0 || $field2 == 0){
return 0;
} elseif ($field1 == 1) {
return 1;
} elseif ($field2 == 2) {
return 2;
}else{
return null;
}
}
}
$test = new test();
print $test->testcal();
You are recreating the function ratingcheck on every iteration of the while loop. You cannot redeclare functions.
You need to move the function outside the loop and then call it from inside the loop.
I have created the following function to fetch data from my database, but its capabilities are limited. Currently it can fetch one value at a time, which is fine for fetching the value of one column of one row, but as I progress with my work, I now want to be able to fetch multiple values in one call.
The Function:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$identifier = (is_null($identifier)) ? "`ID` = '{$_SESSION["ID"]}'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
return $data[$value];
}
mysqli_close($connection);
}
How I currently use it to fetch multiple values:
// Define variables
$x1 = retrieve("x1");
$x2 = retrieve("x2");
$x3 = retrieve("x3");
$x4 = retrieve("x4");
$x5 = retrieve("x5");
$x6 = retrieve("x6");
$x7 = retrieve("x7");
$x7 = retrieve("x8");
I have read other questions here on Stack Overflow, but none of them solves my problem as I use an optional parameter, which makes my life hard. For example, I thought of implementing the splat operator to allow unlimited parameters, but as I use the optional parameter $identifier, I can't make it into something like:
function retrieve($identifier = null, ...$value) {}
because it will use the first parameter as the identifier when I omit it.
I'm sure that regarding performance it would be better if I could fetch all the necessary values in one call of the function retrieve() instead of using it as shown above and that's why I would like to know:
How can I edit this function in order to fetch more values at once?
Calling it like so:
$x = retrieve($y);
$x1 = $y["x1"];
$x2 = $y["x2"];
...
EDIT:
Thanks to Manish Jesani for his help! I used his answer and modified to do exactly what I want. For anyone that may be interested in the future, here's the code:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$values = array();
$identifier = (is_null($identifier)) ? "`ID` = '1'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
if (is_array($value)) {
foreach($value as $_value) {
$values[$_value] = $data[$_value];
}
return $values;
}
else {
return $data[$value];
}
}
mysqli_close($connection);
}
You can call the function with as many parameters you want. Τo do this you have to use func_num_args() to get all of them, as shown below:
function retrieve() {
$args = func_num_args();
$query = "SELECT '".implode("','", func_get_args())."' FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
return $data;
}
mysqli_close($connection);
}
You can call this function like this: $params = retrieve('x1','x2','x3').
Alternatively, you can retrieve them as variables list($x1, $x2, $x3) = retrieve('x1','x2','x3').
Please try this:
function retrieve($value, $identifier = null) {
// Check if identifier is given
$return = array();
$identifier = (is_null($identifier)) ? "`ID` = '{$_SESSION["ID"]}'" : $identifier;
// Connect to the database
$connection = connect("limited");
// Pass query, get result and fetch value out of it
$query = "SELECT * FROM `users` WHERE $identifier";
$result = mysqli_query($connection, $query);
if (mysqli_num_rows($result) > 0) {
$data = mysqli_fetch_assoc($result);
if(is_array($value))
{
foreach($value as $_value)
{
$return[$_value] = $data[$_value];
}
}
else
{
$return[$value] = $data[$value];
}
return $return;
}
mysqli_close($connection);
}
$x = retrieve(array("x1","x2","x3","x4","x5","x6"));
Below is the function I am using. It is strange because when I test the name "admin" it returns an associative array with all the correct columns and values, however every other name tests returns 0 as far as I can tell, meaning nothing is found from the query (I am entering the names perfectly as they are in the database).
I have a feeling this could be some sort of security feature of pdo or something but I don't understand why it is acting up this way.
I am using mysql.
Does anyone know the problem and how to resolve it? Thank you!
function getUserDetailsByName($name, $fields = "*")
{
$db = connect_db();
$query = "SELECT $fields FROM UserDetails WHERE userName=:username";
$result = $db->prepare($query);
$result->bindParam(":username", $name);
if (!($result->execute())) {
sendMessage (1,1,'Query failed',$query);
$db = null;
return;
}
if (!($result->fetch(PDO::FETCH_NUM) > 0)) {
$db = null;
return 0;
}else{
$result = $result->fetch();
$db = null;
return $result;
}
}
EDIT: Someone asked to post how I call the function.
$user = getUserDetailsByName($_POST['value']);
if($user == 0)
{
print "user = 0";
}
print_r($user);
function getUserDetailsByName($name, $fields = "*"){
$db = connect_db();
$query = "SELECT {$fields} FROM UserDetails WHERE userName = :username LIMIT 1;";
if(!$result = $db->prepare($query)){
return null;
}
$result->bindParam(":username", $name);
if(!$result->execute()) {
sendMessage (1,1,'Query failed',$query);
return null;
}
if(!$user = $result->fetch(PDO::FETCH_NUM)) {
return false;
}
return $user;
}
Why 2 fetches? Checkout and compare this to your code.
Use like this:
if($user = getUserDetailsByName($_POST['value'])){
// we have a user!
}else{
// we don't have a user!
}
hello i have problems while using crypt function. i would like to check passwords from a database and an entered one.
the problem i have is that when i will enter a password it even will redirect even in case when it is a totally different password? this is strange to me.
so i use this function:
function salt_crypt($login_password, $rounds = 7) {
$salt = "";
$salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9)); for($i=0; $i < 22; $i++) {
$salt .= $salt_chars[array_rand($salt_chars)];
}
return crypt($login_password, sprintf('$2a$%02d$', $rounds) . $salt);
i will get the stored password from a function that returns an array:
function ab($a){
global $db;
$query = $db->query("SELECT col_a, col_b FROM table WHERE Field= '$a' ");
$check = $query->fetch_assoc();
return ($check);
}
and this will be used in this function:
function login($a, $login_password){
$user_data = user_data($a);
global $db;
$uname = sanitize($uname);
$crypted_password = salt_crypt($login_password);
if(crypt($user_data['col_b'], $crypted_password) == $crypted_password) {
$query = $db->query("SELECT col_a FROM table WHERE Field_a= '$a' AND Field_b = '$crypted_password' ");
$check = $query->num_rows;
return ($check == 1) ? true : false;
}
}
this function wil be called and in case of the returning result header with:
$login = login($a, $login_password);
if ($login === false){
$errors[] = "text";
} else {
header('Location: page.php');
}
Not all code paths return a value -> your function will return true, even if the if statement is false. Try it with something like this:
function login($a, $login_password){
//All your stuff
if(crypt($user_data['col_b'], $crypted_password) == $crypted_password) {
//Your stuff
}
return false
}
if(isset($_POST['uname']))
{
$query = "SELECT * FROM user_info";
$res = $mysqli->query($query);
$num = $res->num_rows;
$i = 0;
$cpwd = $_POST["pswd"];
$hpwd = SHA1($cpwd);
$tmp = $_POST["uname"];
while($i < $num)
{
$row = $res->fetch_object();
$name = $row->Username;
$pwd = $row->Password;
if($name == $tmp)
{
//check if user is blocked
}
//hashed pwd
if($pwd == $hpwd)
{
//success
exit();
}
//request for pwd change
else if($pwd == $cpwd)
{
//change
exit();
}
else if($pwd != $hpwd)
{
//incorrect pwd
}
}
$i++;
}
if($i == $num)
{
//new user
}
}
I'd guess that you're somehow looping past the end of the array and $row is actually NULL.
So $res->fetch_object() did not return an object. Take a look at the documentation of this function. What does it return when it finds nothing?
some times num_rows return 1, even if no rows effected. Try to use
while($row = $res->fetch_object())
or
you forget to increment $i :)
get rid of that junk and make it like this
$query = "SELECT * FROM user_info WHERE Username = ? AND Password = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param('ss', $_POST["uname"], SHA1($_POST["pswd"]));
$stmt->execute() or trigger_error($mysqli->error());
if (!$mysqli->affected_rows) {
//no such user
}
I've never used mysqli myself, so, there may be typos.
But I hope you'll be able to get the idea.