How to tell if error occured in MySQL client script - mysql

I can't discover how to tell if an error occurred in a MySQL client script (after a couple of hours googling and reading the MySQL docs. I would expect there would be something like an error flag or error number that gets set when an error occurs and that you could test this with something like the following:
start transaction
error_flag = false; #just to be safe
...do some work...
... do some more work ...
if ( error_flag == true )
then
rollback
else
commit
;
What's the canonical was of doing this? Am I way off base thinking this approach would work?
Thanks in advancd

$result = mysql_query($query);
if (!$result) {
$errm = "[SQL" . mysql_errno() . "] " . mysql_error();
$this->rollback(); //implement your rollback
throw new Exception($errm);
}
this is the old mysql_* way. Please use pdo instead.

Related

how to inject sql in login process

I've received an old application which completely lacks user input sanitization and is vulnerable to sql injection. To prove gravity of the situation i need to give client an example and what can be better to scare him than the login process. I've tried standard techniques but the problem with them is that they return multiple rows and due to nature of the code it returns an error instead of logging him in. What sql should i inject so that only a single row is returned and the execution reaches "return $access" line in order to pass the value of this "access" column to code calling this login function. The request is made via POST method and magic quotes are off on the server. Please let me know if you need any other information.
function login($username, $pw)
{
global $dbname, $connection, $sqluser, $sqlpw;
$db = mysql_connect($connection,$sqluser,$sqlpw);
mysql_select_db($dbname);
if(!($dba = mysql_query("select * from users where username = '$username' AND password = '$pw'"))){
printf("%s", sprintf("internal error5 %d:%s\n", mysql_errno(), mysql_error()));
exit();
}
$row = mysql_fetch_array($dba);
$access = $row['access'];
if ($access != ''){
return $access;
} else {
return "error occured";
}
mysql_close ($db);
}
Note: it turns out that magic_quotes_gpc is turned on and the php version is 5.2.17
Thanks
Starting with the goal query:
SELECT *
FROM users
WHERE username = '' OR '1'='1'
AND password = '' OR 1=1 LIMIT 1;#'
We get username is ' OR '1'='1 and password is ' OR 1=1 LIMIT 1;#
It depends what values the login function is called with. If there's sanitation before passing it to the function it might actually be safe. However it's better to filter it right before the query so you can see that your built query is safe.
However if you have something like this:
login($_POST['user'], $_POST['pass']);
In that case just put foo' OR 1=1 OR ' in the user field in the login form :)

Issue with cakePHP running unit tests

I've have the weirdest issue while trying to test something in my cakePHP 2.0 app. I have a function inside a model that queries the database to check if the app has already sent a notification in the last 25 days:
public function checkIfNotified($userId){
$query = 'SELECT count(`user_id`) AS notify '.
'FROM `churn_stats` '.
'WHERE `user_id` = '. $userId.' '.
'AND `notified` = 1 '.
'AND TIME_TO_SEC(TIMEDIFF(NOW(),`created`)) <= 2160000 ';
$this->log($query);
$result = $this->query($query);
return $result;
}
I'm doing some Unit tests to check if the method works, so I'm creating a record and trying to test it return return true like so:
$data['notified'] = 1;
$data['user_id'] = $userId;
$this->ChurnStats->create();
$this->ChurnStats->save($data);
$notified = $this->ChurnStats->checkIfNotified($userId);
print_r($notified);
After the result is (which is the wrong result since I've already inserted a row!):
Array
(
[0] => Array
(
[0] => Array
(
[notify] => 0
)
)
)
However I run the exact query generated by the code in the DB and the result is:
I've already lost a lot of time and I don't have any idea what's wrong :(.
After testing and checking everything it was another test function that somehow was changing the DB or the query of the next test, however the weird part was that the other test called the same query but didn't have any insert, update or delete that could modify the results or enviroment of the next test.
After checking everything it all reduced to something: Query Cache, by default CakePHP caches all the $this->query("..."); calls so the fix was quite easy: Deactivate it!
$result = $this->query($query, false);

Mysql delete query won't work on lamp stack

I am doing a project work on php. During my work every single query work smoothly. But when I want to delete any object using it won't delete ...
Here's my php code
<?php
//delete item
if(isset($_GET['deletecat'])){
$id_to_delete = $_GET['deletecat'];
$sql = mysql_query("DELETE FROM `category` WHERE `Category_id`=$id_to_delete LIMIT 1") or die('Error: Could not delete.');
}
else{
header('location: category.php');
exit();
}
?>
and after that I only get the error message.
GET value is OK. And on my phpmyadmin this SQL running OK. But there's a pop up message appear when I want to delete any object. what can I do now?
there's a few layers where you could be having issues: with the db connection, the query, or the data which you are sending.
also, you are not filtering for " and ' marks so you could be in trouble there, and you're not ensuring that your id is a number so your sql could also be failing there.
but, you can figure that out with a few adjustments to your code.... you can insert some diagnostics into your code to see what mysql is reporting the error as and get a better idea of how to fix it.
note that it is [generally recommended][1] to use mysqli extension instead of mysql extension, but irregardless, here's sample code with the extension you are currently using
hope this helps!
<?php
if ( isset($_GET['deletecat'])) {
#dbh -> database resource.
$dbh = mysql_connect()
#mysql_connect returns false if it fails. capture error and echo to output.
if (!$dbh) {
die("Could not connect to database server: ".mysql_error()."\n");
#if using mysqli use mysql_connect_error() instead
}
#never trust input. use an escape function.
$id_to_delete = mysql_real_escape_string($_GET['deletecat'],$dbh);
#force $id_to_delete to be treated as a number, or make it safer in your sql.
#i used the latter method below.
$sql = "DELETE FROM `category` WHERE `Category_id` = '$id_to_delete' LIMIT 1");
#mysql_query returns false on failure
$result = mysql_query($sql,$dbh);
#on failure catch the error and display the exact contents of 'deletecat' in a web-friendly way.
if (!$result) {
$error=mysql_error($dbh);
die ("Error: Could not delete '"
.htmlentities(print_r($_GET['deletecat'],true)).". Error: $error\n"
);
}
#if we did not trigger die() above we are ok.
header('location: category.php');
exit();
}
?>
:
[1]: see warning at http://php.net/manual/en/function.mysql-connect.php
You should escape the GET variable first to avoid any SQl injection attacks as already said by deceze. Then, you should understand that the message given by phpmyadmin is a confirmation if you need to execute the delete query. you can use mysql_real_escape_string($value) to escape but as php vendor says, this function will be removed very soon and is currently deprecated.
bye..

How does $this->db->trans_status() work in codeigniter transactions?

How exactly does $this->db->trans_status() in CodeIgniter understand that whether the queries in the transaction were successful or not?
Source: http://codeigniter.com/user_guide/database/transactions.html
$this->db->trans_begin();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->query('AND YET ANOTHER QUERY...');
if ($this->db->trans_status() === FALSE){
$this->db->trans_rollback();
}
else{
$this->db->trans_commit();
}
Am using MySQL as the underlying database
SQL has a statement for START TRANSACTION one COMMIT and one for ROLLBACK.
Your database driver and/or abstraction layer doesn't have to send the entire list at once:
$query_string = '
START TRANSACTION;
SELECT something FROM somewhere;
UPDATE something SET something.we_have = something.else;
COMMIT;';
$dba->execute($query_string);
They can be sent individually and the driver and/or abstraction layer can wait for the query to execute and return an SQL STATUS.
$query_string = 'START TRANSACTION;';
$dba->execute($query_string);
$query_string = 'SELECT something FROM somewhere;';
$dba->execute($query_string);
$query_string = 'UPDATE something SET something.we_have = something.else;';
$dba->execute($query_string);
$status = $dba->get_status();
if($status)
$query_string = 'COMMIT;';
else // darn our update must have failed
$dba->execute($query_string);
And based on that status you can decide weather to COMMIT or ROLLBACK.
Of course this implies that the overall time spent by your script in connecting to the DB is bigger than if it would've just shoved the entire string down the pipe in one connection.
This is a mess:
if($status)
$query_string = 'COMMIT;';
else // darn our update must have failed
$dba->execute($query_string);
Maybe you want:
if($status)
$query_string = 'COMMIT';
else // darn our update must have failed
$query_string = 'ROLLBACK';
$dba->execute($query_string);

Query only working on PHPMyAdmin

I'm trying this query:
//connect;
$site = mysql_real_escape_string($_GET['site']);
$data = mysql_query("SELECT * FROM Items WHERE Site = '$site'");
while($row = mysql_fetch_array( $data ))
{
print $row['type'];
}
doesn't print anything, running SELECT * FROM Items WHERE Site = 'http://rollingstone.com/' from PHPMyAdmin returns one row.
I'm sure it must be something really basic, since I haven't got much experience with MySQL.
I'm trying it here btw: http://www.chusmix.com/game/insert/get-items.php?site=http://rollingstone.com/
What am I doing wrong?
Make sure $site actually contains something; doing a quick echo $site before your mysql_query() should tell you this. If it's empty, try print_r($_GET) to see if it's in the $_GET array. It should be, but it might not for some other reason; check any code above this snippet for stuff that modifies $_GET or $_REQUEST in any way.
To request data from a MySQL table, you need to connect to the server using mysql_connect(), then select the database with mysql_select_db(). PHP should throw errors, but to be sure put these lines at the top of your script:
error_reporting(E_ALL);
ini_set('display_errors', '1');
All errors will now be shown.
In addition, you can also test for how many rows that were returned using mysql_num_rows(). For example:
if(mysql_num_rows($data) !== false)
{
while(...)
{
...
}
}
else
{
echo "No rows";
}
Will echo No rows if there weren't any results from the query. This is all error detection code; the cause of your error isn't obvious, so a little investigation is necessary, using the above methods (and any more you can think of).
Have you called mysql_select_db('your_database_name'); on the connection first? Have you tried echoing out the SQL before it's executed to confirm that Site is what you expect it to be?
$query = sprintf("SELECT * FROM Items WHERE Site ='%s'",
mysql_real_escape_string($site));
$result = mysql_query($query);
Just to be on the safe side (avoid SQL Injections).