Hi
I've created a DBAL module for a framework, And added Prepared Statements support to it. Here's the whole class code:

<?php
/*
 * Database Access Layer
 * by AbiusX[at]gmail[dot]com
 * Version 2.2.1
 * Customized for MySQL
 */
	//TODO: the current fetch method for Prepared Statements copies the arrays so badly!	
	//TODO: add support for transactions
	//TODO: add support for stored procedures
	//TODO: add support for triggers and Vies
	class DBAL {
		public $DB;
		public $Result;
		public $m_username,$m_password,$m_databasename;
		public $QueryCount;
		function __construct($Username,$Password,$DatabaseName)
		{
			$this->DB=new mysqli("localhost",$Username,$Password,$DatabaseName);
			if (mysqli_connect_errno())
				die( "Unable to connect to database.");
			//$this->DB->select_db($DatabaseName);
			$this->m_username=$Username;
			$this->m_password=$Password;
			$this->m_databasename=$DatabaseName;


	}
	function __destruct()
	{
		$this->DB->close();
	}
	function LastInsertID()
	{
	    return $this->LastID();
	}
	function LastID()
	{	
		return $this->DB->insert_id;
	}
	function Escape()
	{
		$args=func_get_args();
		foreach ($args as $arg)
			$this->DB->real_escape_string($arg);
	}
	function Query($QueryString)
	{
		$this->QueryCount+=1;
	    $this->Result=$this->DB->query($QueryString);
	}
	function NextResult()
	{
		if ($this->ResultCount())
		return $this->Result->fetch_array(MYSQLI_ASSOC);
		else
		return false;
	}
	function AllResult()
	{
		if ($this->ResultCount())
		{
			$out=array();

			while ($r=$this->Result->fetch_array(MYSQLI_ASSOC)) $out[]=$r;

			return $out;
		}
		else return false;
	}
	function ResultCount()
	{
		return $this->Result->num_rows;
	}
	function AffectedRows()
	{
		return $this->DB->affected_rows();
	}

	function FullQuery($QueryString)
	{
		$this->Query($QueryString);
		return $this->AllResult();
	}
	function AutoQuery($QueryString)
	{
		return $this->FullQuery($QueryString);
	}
	function AutoPrepared()
	{
		$st=new PreparedStatement($this);
		$args=func_get_args();
		return call_user_func_array(array($st,"Auto"),$args);
	}
	function AutoPrepare()
	{
		$args=func_get_args();
		return call_user_func_array(array($this,"AutoPrepared"),$args);
	}
	function Execute()
	{
		$args=func_get_args();
		return call_user_func_array(array($this,"AutoPrepared"),$args);
	}
	function RunPrepared()
	{
		$args=func_get_args();
		return call_user_func_array(array($this,"AutoPrepared"),$args);
	}
}
class PreparedStatement {
	public $DB;
	public $Statement;
	public $DBAL;
	function __construct(DBAL $DB,$Query=0)
	{
		$this->DB=$DB->DB;
		$this->DBAL=$DB;

		if ($Query)
			$this->Prepare($Query);
	}
	function Auto($Query)
	{
		$IID=false;
	    $this->Prepare($Query);
		if (substr(strtoupper($Query),0,6)=="INSERT" or substr(strtoupper($Query),0,7)=="REPLACE" )
			$IID=true;

		if (func_num_args()>1)
		{
			$args=func_get_args();
			array_shift($args);
			//array_shift($args);
			call_user_func_array(array($this,"Bind"),$args);
			$this->Execute();
			if (!$IID) return $this->AllResult();
			else return $this->LastID();
		}
	}
	function Prepare($QueryString) //replace values with ?
	{
		if (!$stmt=$this->DB->prepare($QueryString))
			die ("Unable to prepare statement: ".$QueryString." reason: ".$this->DB->error);
		$this->Statement=$stmt;
	}
	function __destruct()
	{
		if ($this->Statement) $this->Statement->close();
	}
	private function VarType($var)
	{
		if (is_string($var))
			return "s";
		elseif (is_float($var) or is_double($var))
			return "d";
		elseif (is_bool($var) or is_int($var) or is_long($var))
			return "i";
		else 
			return "b";

	}
	function Bind()
	{
		$args=func_get_args();
		$types="";
		/*
		foreach ($args as $arg)
		{
			$types.=$this->VarType($arg);
		}
		*/
		$types=str_repeat("s",count($args));
		$newarr=array_merge(array($types),$args);


		call_user_func_array(array($this->Statement
			,'bind_param')
			,$newarr);


	}
	function Execute()
	{
		$this->DBAL->QueryCount+=1;
		$this->Statement->execute();
	}
	function ResultCount()
	{
		return $this->Statement->num_rows();
	}
	function LastID()
	{	
		return $this->Statement->insert_id;
	}
	function NextResult() 
	{
		$data = $this->Statement->result_metadata();
    	$fields = array();
    	$out = array();

    	$count = 0;

    	while($field = mysqli_fetch_field($data)) 
        	$fields[$count++] = &$out[$field->name];

    	call_user_func_array(array($this->Statement,"bind_result"), $fields);
    	$this->Statement->fetch();
    	return (count($out) == 0) ? false : $out;   		
	}
	function AllResult()
	{
		$data = $this->Statement->result_metadata();
		if (!$data) return ;
		$fields = array();
    	$out = array();

    	$count = 0;

    	while($field = mysqli_fetch_field($data)) 
        	$fields[$count++] = &$out[$field->name];

    	call_user_func_array(array($this->Statement,"bind_result"), $fields);
    	$output=array();
    	while ($this->Statement->fetch())
    		$output[]=unserialize(serialize($out)); //TODO: fix here
    	return (count($output) == 0) ? null : $output;   		
	}
}

?>

The problem is with the last lines of code where I say
$output[]=unserialize(serialize($out)); //TODO: fix here
I know that when you code $a=$b;
and both are arrays, the arrays are copied. So I assume when I add $out to $output, A copy of it would be added, but it wont. And nothing seems to work, So I had to call a few functions on it to copy it actually!
If I do not copy it, All the result rows would be the last row!

Please help?

    I didnt read through your code thoroughly...

    Do you call $stmt->bind_result()
    anywhere or could that be missing/going wrong?

      You just need to read my last function in the code.
      And you can also download the old framework code (version 1.85) from www.jframework.sbce.ir

      which has the same DBAL as this.

      Of course I do call bind_result, but since I was gonna code a wrapper function to run the whole prepared statement and return the resultset, I had to use call_user_func to pass all the params. You can find it in the last function of the code.

      The problem is when I bind results to variables, They get referenced and when I try to copy those variables, They won't! only the references get copied.

      I dunno what to do

        function AllResult() 
                { 
                    $data = $this->Statement->result_metadata(); 
                    if (!$data) return ; 
                    $fields = array(); 
                    $out = array(); 
        
                $count = 0; 
        
                while($field = mysqli_fetch_field($data)) 
                    $fields[$count++] = &$out[$field->name]; 
        
                call_user_func_array(array($this->Statement,"bind_result"), $fields); 
                $output=array(); 
                while ($this->Statement->fetch()) 
                    $output[]=unserialize(serialize($out)); //TODO: fix here 
                return (count($output) == 0) ? null : $output;            
            } 

        I don't quite understand this function. First you initialize $out, so it is empty...then you fill it with what and where and with what intention? Then you want to pass the array $out once for every record in your queryresult to a new entry in the $output array? Huh? Are those two while statements meant to be completely unrelated? Maybe add {} around your while statements even when using only one statement and use if () {} instead of the ? : syntax, just to make things easier to read.

          lol
          ok sorry for code complexity, just lemme explain.

          The code is intented to bind enough variables as result to be able to fetch a whole row of result dataset.
          So I first create an array with keys which are names of the table fields in database.
          Then I create another numeric array, and reference every member of it to my first array,
          Third I bind_results the fields array. Its like this:
          $fields[1]= & $out[ID];
          $fields[2]= & $out[Username];
          Statement->bind_result($fields[1],$fields[2]);

          which is equal to
          Statement->bind_result($out[ID],$out[Username]);

          So everytime i fetch a row from result set, I get $out array filled with data. And I can access all the fields of the row with their responsive keys.

          Now I just want to have a whole result set in a 2D array, So while i have rows to be fetched, I fetch them, And add them to another array:
          While( there are rows to fetch )
          {
          $out=fetchit();
          $output[]=$out;
          }

          in the end, $output should be the desired 2D array i've been looking for.
          But unexpectedly, When I do so, $output would be a 2D array with same rows!

          e.g my db would contain:
          ID Username
          1 AbiusX
          2 XsuibA

          But the output has
          [0]=> array([ID]=>2 , [Username]=>XsuibA) , [1] =>array([ID]=>2, [Username]=>XsuibA)
          As you see, All data are repeated. I think this is because the $output array holds referenced to $out in every new set, Instead of copies from $out.

          So I wanted a method to copy $out into $output[]..
          When i surfed the net, the only way to copy an array was to say $a=$b;
          but this isnt working for sure in my case, So I used 2 functions to counter each other and get the result, But serialization and deserialization is greatly decreasing the performance here.

          Any ideas?

          but in a dynamic manner.

            My ideas are as follows:

            In php manual about stmt::fetch read the 4 user notes up from (and including) the one by "dan dot latter at gmail dot com" from "16-Aug-2007 07:14".

            Then forget about prepared statements for this task - it introduces more problems than it can possibly solve.

            Then do a regular query (mysqli->query($sqlstring)) and use mysqli_result::fetch_assoc. Less of a headache, less hax, more reliable, faster.

            Bjom

              hmm

              the normal query isnt always faster, but I'm using this prepared statement method for a framework, not for myself, So even if a novice programmer codes something without considering SQL Injection in mind, There won't be any security measures on this.

              So I'm just gonna stick to prepared statements, but tanx for the PHP Manual

                since they are supposed to use your function you can apply all the input sanitation that you like before running the query.

                mysqli->real_escape_string will do a good job.

                It would most likely be faster in this case because there is less processing after running the query.

                Bjom

                  real_escape_string is not even near secure! 😃 it only does the trick for basic injections. There are millions of way to bypass it. To be clear, There are no other ways except prepared statements that prohibit injections, So I'm strongly focused on using them.

                    AbiusX wrote:

                    real_escape_string is not even near secure! it only does the trick for basic injections. There are millions of way to bypass it.

                    Assuming that it is used correctly, and excluding bugs in its implementation, I believe that that is false, and if not certainly greatly exaggerated. The problem is that it is harder to use correctly than prepared statements.

                      laserlight, I'm currently working on OWASP PHP ESAPI project at www.owasp.org . i Think you mighgt be wrong. It is not secure. You can just assume it secure for novice hackers

                        AbiusX wrote:

                        i Think you mighgt be wrong. It is not secure.

                        It is certainly possible that I might be wrong. However, the burden of proof is then on you to show that I am wrong even when the function is used correctly and with bugs in its implementation accounted for. I am otherwise not convinced, since I have neither seen nor can I think of a way to circumvent it that does not rely on either incorrect usage or an implementation bug, or both.

                        Consequently, I think that prepared statements are better, but in the cases that you are trying to account for, an appropriate escaping function will suffice.

                          Funny, I am also unaware of one, letalone millions, of insecurities in mysql_real_escape_string.

                          I am also wondering where the abstraction layer is in your code...Typically this might be done using a strategy. Here it seems your stuck with mysqli. This might be better named a mysqli wrapper, although why would you want one?

                            The abstraction is in its interface. As you can see this class follows a particular interface which can be implemented for any other relational database.
                            and this isn't a wrapper for MySQLi since there are a few more supports added here and there.

                            Check the SQLi section at owasp.org to know why real_escape_string isn't even near secure, Or tell me any website you've developed and let me crack it in a matter of minutes 😃 no offence

                              AbiusX wrote:

                              Check the SQLi section at owasp.org to know why real_escape_string isn't even near secure,

                              Where exactly is the SQLi section at owasp.org? I tried searching, but none of the articles that were listed pointed out flaws in any variant of real_escape_string that were due to inherent problems rather than incorrect use. It would be good if you could provide a link to an article that describes the problems explicitly.

                              AbiusX wrote:

                              Or tell me any website you've developed and let me crack it in a matter of minutes no offence

                              No offence taken. But do you not see the problem? If you succeed, maybe it is because the developer did not use real_escape_string correctly, or maybe because you exploited a bug in that particular implementation. If you fail, does that really mean that real_escape_string is secure? Maybe it does have inherent vulnerabilities, but your skills and knowledge of the system were insufficient for you to execute a successful attack. Either way, that does not prove anything with respect to my assertion, i.e., that real_escape_string is not insecure in itself, even though it is easier to use incorrectly than bound parameters in prepared statements.

                                Try OWASP presentations. There are two particulars on SQLi, namely "Advanced Topics in SQL Injection Protection" and "Advanced SQL Injection" as I can remember.

                                Also you can try ha.ckers.org for SQL Injection Cheat Sheet and methods to bypass escaping. This is not a general case, But deep consideration should be taken to make it secure.

                                What I meant earlier was that no enterprise CAN BE IMMUNE using real_escape_string, since there are always flaws in using it.

                                What you're telling is that if you use it correctly enough, No problems would be faced. But you gotta know that if you use everything correctly and implement everything properly, There would be nor bugs neither security flaws in your application.

                                How can you make sure you've everything implement properly? By spending huge amounts of budget on security measurement.

                                Conclusion => escaping is almost useless in security.

                                  AbiusX wrote:

                                  What I meant earlier was that no enterprise CAN BE IMMUNE using real_escape_string, since there are always flaws in using it.

                                  Now I agree with you, since this is the same point that I am making, though it is stated stronger than I would state it.

                                  AbiusX wrote:

                                  What you're telling is that if you use it correctly enough, No problems would be faced. But you gotta know that if you use everything correctly and implement everything properly, There would be nor bugs neither security flaws in your application.

                                  This is the principle of ceteris paribus: since you stated that real_escape_string was inherently insecure by itself, I eliminated other considerations that I would otherwise have considered in order to be sure that we were talking on common ground.

                                  Unfortunately, I do not think this part of the discussion has helped you very much, but I do not have time right now to formulate a reply directly concerning your question... but I'll be back 🙂

                                    AbiusX;10919146 wrote:

                                    The abstraction is in its interface. As you can see this class follows a particular interface which can be implemented for any other relational database.
                                    and this isn't a wrapper for MySQLi since there are a few more supports added here and there.

                                    Thus what you have defined is an interface, not really a database abstraction layer. The implementation is mostly a wrapper of the mysqli extension. The implementation of MySQL specific logic could be provided as a Strategy, separating the interface from the implementation.

                                    AbiusX;10919146 wrote:

                                    Check the SQLi section at owasp.org to know why real_escape_string isn't even near secure, Or tell me any website you've developed and let me crack it in a matter of minutes 😃 no offence

                                    Consider the following:

                                    $username = mysql_real_escape_string( $_GET['username'] );
                                    execute_sql( "SELECT username FROM the_table WHERE username = '" . $username . "'" );
                                    

                                    How would you approach "cracking it in a matter of minutes"? Suggesting that escaping is a "almost useless" is a nonsense since the lack of it is the most common vector in a SQL injection. Certainly prepared statements offer blanket protection against injection but that does not invalidate other methods.

                                    I took the time to read through "Advanced Topics in SQL Injection" and while the information in there is certainly valid, it made some rather large assumptions about how people might craft SQL statements.

                                      I'm wondering how you make websites with only two lines of code 🙂 Surely your webs won't be cracked by anyone!

                                      I'd rather people responding to my main question instead of toying 🙂 What kinda forum is this?