[PHP] RE:[PHP] login problem fixed!!
[snip] please note this will only catch invalid queries. To catch the event of the query being perfectly fine, but nothing coming back, just check the values of num_rows or affected_rows (depending on the query). [/snip] um?? this way doesnt work for some strange reason... testing affected_rows returns always with 0 so: if(mysql_affected_rows()==0){...} will always get ran even if the query itself returned an invalid user login... num_of_rows will always return true and never false i guess because when $result (the query itself) is invalid or returns the fact that the user typed a wrong username and or password the db server returns NULL, false or rightfully 0. thus the error: num_of_rows() is not a valid resource type in:..login.php error so as far as i know i have to test the literall existance of the $result resource being true (a real login) or false (the login failed)... at this point i cant test for $_SESSION['username'] because it hasnt been registered yet... anyhow..off my soap box -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] RE:[PHP] login problem fixed!!
Hello Andy, Thursday, March 25, 2004, 9:53:05 AM, you wrote: AB um?? this way doesnt work for some strange reason... testing AB affected_rows returns always with 0 so: AB if(mysql_affected_rows()==0){...} It depends on your query. If you are doing a SELECT query then you cannot use affected_rows, you must use num_rows instead. If you are doing an UPDATE or INSERT query then swap that over. AB num_of_rows will always return true and never false i guess because when mysql_num_rows will never return true OR false because it doesn't return a boolean, it returns a value, so you cannot check its contents like this. AB $result (the query itself) is invalid or returns the fact that the user AB typed a wrong username and or password the db server returns NULL, false or AB rightfully 0. thus the error: AB num_of_rows() is not a valid resource type in:..login.php error mysql_query ONLY returns a FALSE if the query fails for SELECT queries (and show/explain/describe, but that's not relevant to this). If your query is perfectly valid but simply returns no data, you can only check for this with mysql_num_rows. Your logic sequence should be as follows: 1. Send query to MySQL 2. Check if mysql_errno == 0 If it DOESN'T, your query had an error, so find out what it was by echoing out mysql_error() and quitting gracefully. 3. If mysql_errno == 0 then your query ran perfectly, so... 4. Check value of mysql_num_rows. If == 0 then simply no data was returned, so handle the error accordingly. If value == 1 then you know you've got the data back that you wanted. For INSERT/UPDATE queries substitute mysql_num_rows in the above for affected_rows, principle is the same though - but be careful when comparing your data types for affected rows. -- Best regards, Richard Davey http://www.phpcommunity.org/wiki/296.html -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP] re:[PHP] login problem fixed!!
So, just for the sake of me getting this right, it would be better code if i had the code like this: ? $UserExists=mysql_query(select * from users where username='$_POST[username]' and pwd=md5($_POST[password])); //since query is done see if the user exists if($UserExists) { ExistingUserCanDoSomething(); } else { YouCantDoAnythingIfYouDontExist(); } ? forgive the odd severely long redundant example names but... im sure that is better than what i had before... let me know if i got the right idea... and $UserExists in this example is either true or false because empty set in mysql isnt even a number it = NULL echo $UserExists;//prints 0 if false and 1 if true //at least in this instance of it (normally it would return total rows matched) at the point of logins i dont care about the # of rows it will alwas return 0 or 1 so true/false is best for me right now. when i create the user generater then i will need to check for multiple usernames/passwords (2 users cant have the same pwd or id)... anyways...off my box again -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] re:[PHP] login problem fixed!!
Hello Andy, Thursday, March 25, 2004, 10:43:54 AM, you wrote: AB So, just for the sake of me getting this right, it would be better code if i AB had the code like this: AB ? AB $UserExists=mysql_query(select * from users where AB username='$_POST[username]' and pwd=md5($_POST[password])); AB //since query is done see if the user exists AB if($UserExists) { AB ExistingUserCanDoSomething(); } AB else { AB YouCantDoAnythingIfYouDontExist(); } ? Do you actually need to bring back the user data? What I mean is, you're selecting * from the users table and doing nothing with it other than worrying if the query was successful or not. It would make far more sense if you just did this: SELECT COUNT(username) AS hits FROM users WHERE ... Providing your query syntax is good this will always return a value in hits. A zero means no users, anything above and you've got a live one. Also - I doubt I need to mention this, but you're injecting POST variables directly into a SQL query. I hope your example above was just that and isn't the actual way you're doing it? AB and $UserExists in this example is either true or false because empty set AB in mysql isnt even a number it = NULL $UserExists in your example will never be TRUE, it can only ever be FALSE. mysql_query does not, under any circumstances, return a boolean TRUE value. It either returns a FALSE (if it was a select query) or a *resource identifier* regardless of empty sets. Sometimes if this resource identifier equals the value of 1 then a loose comparison to true might exist, but only because PHP is determining this value as such, not because it really is a true boolean value. In the example above, providing all the data is given (username and password) the query will return what appears to be TRUE regardless of what happens. Imagine you have a user bob in your database and his password is hi, look at the two following queries: SELECT * FROM users WHERE username='bob' AND password='hi' SELECT * FROM users WHERE username='bob' AND password='incorrect' Both of them will make mysql_query return a resource identifier because they are both correct from a syntax point of view. But in actual fact they're telling you two completely different things. Without doing a COUNT or knowing how many rows the query returned, you cannot determine if the user does already exist or not, all you can tell is if your query worked and an invalid user does not = an invalid query. -- Best regards, Richard Davey http://www.phpcommunity.org/wiki/296.html -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP] re:[PHP] login problem fixed!!
Do you actually need to bring back the user data? What I mean is, you're selecting * from the users table and doing nothing with it other than worrying if the query was successful or not. ops!! I forgot to mention that the username is used elsewhere in a different file somewhere (to verify the session exists and stuff). thats the only thing directly used elsewhere... as far as the password thing goes it needs to know if they put in the right username and password (i.e. a row that has the username/password they put in). It would make far more sense if you just did this: SELECT COUNT(username) AS hits FROM users WHERE ... dont know because then how would i verify that the valid user was logged in or if they typed the wrong stuff in?? Providing your query syntax is good this will always return a value in hits. A zero means no users, anything above and you've got a live one. very true...might come in handy for the register a user part Also - I doubt I need to mention this, but you're injecting POST variables directly into a SQL query. I hope your example above was just that and isn't the actual way you're doing it? yikes!! good thing this is just a testing site...how to insert them if $_POST isnt the right way then?? and $UserExists in this example is either true or false because empty set in mysql isnt even a number it = NULL $UserExists in your example will never be TRUE, it can only ever be FALSE. mysql_query does not, under any circumstances, return a boolean TRUE value. It either returns a FALSE (if it was a select query) or a *resource identifier* regardless of empty sets. Can we disagree here? if i take my original query (at the top of this email) and assign the result of it to a variable $UserExists like we did above and test it: if($UserExists) {//assuming the server found anything to start with echo $UserExists; //fortunately the server found a match somewhere because //the result of printing $UserExists is Resource id #4 } else {//what if the server couldnt find a valid row?? echo $UserExists;//results in a blank screen assuming the //server couldnt create the resource id because of no valid //matching rows } on the other hand if i didthis: if(num_of_rows($UserExists){ echo num_of_rows($UserExists);//will get 1 } else { echo num_of_rows($UserExists);//will get: warning: not a //valid resource identifier for num_of_rows } now if i just did: select * from users for num_of_rows i would get 3 for an answer because there are 3 rows in the table... and the else part would never be used... Sometimes if this resource identifier equals the value of 1 then a loose comparison to true might exist, but only because PHP is determining this value as such, not because it really is a true boolean value. if that is so, then how do you explain the above?? In the example above, providing all the data is given (username and password) the query will return what appears to be TRUE regardless of what happens. Imagine you have a user bob in your database and his password is hi, look at the two following queries: again, explain the above... SELECT * FROM users WHERE username='bob' AND password='hi' SELECT * FROM users WHERE username='bob' AND password='incorrect' different for sure...if your saying that i would still get a resource id from both of those on my example then why does it somehow know the difference? Both of them will make mysql_query return a resource identifier not if the comparison between the username/pwd from the form and the db are different...then they wouldnt be the same thing (thats why i compare the username against the password) because they are both correct from a syntax point of view. But in actual fact they're telling you two completely different things. agree but im not testing the syntax Without doing a COUNT or knowing how many rows the query returned, you cannot determine if the user does already exist or not, all you can tell is if your query worked and an invalid user does not = an invalid query. sorry for repeating but somehow it knows the difference... -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] re:[PHP] login problem fixed!!
Hello Andy, Thursday, March 25, 2004, 11:57:09 AM, you wrote: AB SELECT COUNT(username) AS hits FROM users WHERE ... AB dont know because then how would i verify that the valid user was logged in AB or if they typed the wrong stuff in?? Because it works like this: SELECT COUNT(username) AS hits FROM users WHERE username='$u' AND password='$p' So.. if hits = 0, then no user with that username and password combination exists. If hits = 1 (or more!) then the user exists and their password matches. MySQL will run a COUNT query much faster than a SELECT, especially if you have the main columns indexes. AB yikes!! good thing this is just a testing site...how to insert them if AB $_POST isnt the right way then?? Extract the values before-hand: $username = $_POST['username']; Now run tests on $username. For example - should it be a minimum of 3 characters? If so, use strlen to test this. Should it most certainly not contain HTML? Then run it through strip_tags. Remove any extra spaces that might be entered with trim(). Etc etc - you get the idea :) The final $username can be fed into your query far more safely than before. AB Can we disagree here? if i take my original query (at the top of this email) AB and assign the result of it to a variable $UserExists like we did above and AB test it: AB if($UserExists) {//assuming the server found anything to start with AB echo $UserExists; AB //fortunately the server found a match somewhere because AB //the result of printing $UserExists is Resource id #4 This doesn't mean the server found a match, it means your query didn't have any SQL syntax errors in it. An empty set is still a valid resource, but it doesn't mean the given user does (or does not) exist. AB now if i just did: select * from users for num_of_rows i would get 3 for an AB answer because there are 3 rows in the table... and the else part would AB never be used... You're not counting how many users are in the table, you're counting to see if the username and password you gave exists, like so: SELECT * FROM users WHERE username='$username' AND password='$password' Then you check mysql_num_rows. It will equal 0 if no user was found matching your combination, or it will return a number. If you have set your table so that Username must be unique (which would be a sensible thing to do) then it could only ever return a 0 or a 1. AB Sometimes if this resource identifier equals the value of 1 then a loose AB comparison to true might exist, but only because PHP is determining this AB value as such, not because it really is a true boolean value. AB if that is so, then how do you explain the above?? Like I said, PHP is turning your resource identifier into a boolean and assuming anything 0 is TRUE. AB not if the comparison between the username/pwd from the form and the db are AB different...then they wouldnt be the same thing (thats why i compare the AB username against the password) The MySQL query function doesn't care about the query itself, it's just a means to pass it to the database. The result doesn't contain any row information at all, just a resource which PHP uses to retrieve the data via further functions. See the following code I just wrote to double-check this: First I created a MySQL database + table as such: CREATE DATABASE test CREATE TABLE `users` (`username` VARCHAR (30), `password` CHAR (32)) INSERT INTO users (username, password) VALUES ('rich', 'e1bfd762321e409cee4ac0b6e841963c') INSERT INTO users (username, password) VALUES ('andy', '81c3b080dad537de7e10e0987a4bf52e') There we have 2 users (rich and andy), the passwords are MD5 hashes of php and mysql. I.e. the password for rich is php and andy is mysql. You can save the following HTML/PHP into a file somewhere in your web directory, it should run without modification other than perhaps the MySQL server/username/password. -- Cut from here -- html head titleMySQL Test/title /head body form action=?=$_SERVER['PHP_SELF']? method=post Username: input type=text name=usernamebr Password: input type=text name=passwordbr input type=submit /form ?php mysql_connect('localhost','root',''); mysql_select_db('test'); $username = $_POST['username']; $password = $_POST['password']; $sql = SELECT * FROM users WHERE username='$username' AND password=MD5('$password'); if (isset($_POST['username'])) { $result = mysql_query($sql); echo $result . br; } echo pre; print_r($_POST); echo /pre; echo Rows Returned: . mysql_num_rows($result) . br; echo Comparing \$result to TRUE: if (\$result) : br; if ($result) { echo Valid user; } else { echo Error?; } ? /body /html -- End here -- Now if what you're saying is correct, the final if result() block should only print valid user if the user exists in the
[PHP] re:[PHP] login problem fixed!!
if ($result) { echo Valid user; } else { echo Error?; } ? /body /html -- End here -- Now if what you're saying is correct, the final if result() block should only print valid user if the user exists in the database, right? yup and believe it or not if($result) only returns true if a valid username/password row can be found otherwise it returns a non existing resource For me it'll print valid user no matter what I do because the query is always valid and that is all it's checking. hmmm interesting... in your example of usernames here, when i type andy for username and mysql for password it says valid user. now say i type andy for a username and junk for a password it will now say error? because in mysql's mind set there isnt any row anywhere that exists with andy for a username and junk for a password. now take it the other way around: i type useless for a username and mysql for a password and then it still says: error?... it seems that no matter what i do (unless you directly spoof the mysql server) it cannt be fooled at all... at this point it is acting like it is indistructable (i know what a wild dream) but have to have one for a min ... in any case i cant find any loop holes in it anywhere... the only thing i see i can do to reduce risk of hacks or possible outside interference is to turn $result in your example into a session var $_SESSION['result']. since $result can be changed from the query string from a link (wait testing...) well doesnt exactly work but crashes it instead being a global like that... If I enter a valid username and password combo the result is reflected in mysql_num_rows, as shown in the code. yup...it does on mine too... just like you say Unless I have missed something significant from your original code/query I'm at a complete loss as to how the above can give you any kind of different result? thats a good question i cant even answer... -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] re:[PHP] login problem fixed!!
Hello Andy, Thursday, March 25, 2004, 1:17:54 PM, you wrote: AB yup and believe it or not if($result) only returns true if a valid AB username/password row can be found otherwise it returns a non existing AB resource Absolutely fascinating, I have never seen a MySQL server behave like this. Could you post which version of MySQL you're using and perhaps the MySQL part of phpinfo()? There must be something *somewhere* that controls this behaviour. All I can say for certainty is that if I uploaded your code onto my web host, it'd fail. So long as you're building this in a controlled environment and you know where it's going to go when it's live, then I guess you can exploit this to its full potential. -- Best regards, Richard Davey http://www.phpcommunity.org/wiki/296.html -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP] re:[PHP] login problem fixed!!
Absolutely fascinating, I have never seen a MySQL server behave like this. Could you post which version of MySQL you're using and perhaps the MySQL part of phpinfo()? There must be something *somewhere* that controls this behaviour. PHP Version 4.0.4pl1 Linux noir.propagation.net 2.0.36 #5 Wed Dec 16 18:09:02 CST 1998 i686 unknown Apr 10 2001 Configure Command './configure' '--with-apache=../apache_1.3.19' '--with-config-file-path=/etc' '--with-msql' '--without-gd' PHP Core Table with 3 columns and 59 rows Directive Local Value Master Value allow_call_time_pass_reference On On allow_url_fopen 1 1 arg_separator asp_tags Off Off auto_append_file no value no value auto_prepend_file no value no value browscap no value no value default_charset no value no value default_mimetype text/html text/html define_syslog_variables Off Off disable_functions no value no value display_errors On On display_startup_errors Off Off doc_root no value no value enable_dl On On error_append_string Off Off error_log no value no value error_prepend_string Off Off error_reporting no value no value expose_php On On extension_dir /usr/local/lib/php/extensions/no-debug-non-zts-20001214 /usr/local/lib/php/extensions/no-debug-non-zts-20001214 file_uploads 1 1 gpc_order GPC GPC highlight.bg #FF #FF highlight.comment #FF8000 #FF8000 highlight.default #BB #BB highlight.html #00 #00 highlight.keyword #007700 #007700 highlight.string #DD #DD html_errors On On ignore_user_abort Off Off implicit_flush Off Off include_path .:/usr/local/lib/php .:/usr/local/lib/php log_errors Off Off magic_quotes_gpc On On magic_quotes_runtime Off Off magic_quotes_sybase Off Off max_execution_time 30 30 open_basedir no value no value output_buffering Off Off output_handler no value no value post_max_size 8M 8M precision 14 14 register_argc_argv On On register_globals On On safe_mode Off Off safe_mode_exec_dir 1 1 sendmail_from no value no value sendmail_path /usr/sbin/sendmail -t -i /usr/sbin/sendmail -t -i short_open_tag On On SMTP localhost localhost sql.safe_mode Off Off track_errors Off Off upload_max_filesize 2M 2M upload_tmp_dir no value no value user_dir no value no value variables_order no value no value y2k_compliance Off Off table end mysql Table with 2 columns and 7 rows MySQL Support enabled Active Persistent Links 0 Active Links 0 Client API version 3.23.22-beta MYSQL_INCLUDE MYSQL_LFLAGS MYSQL_LIBS table end Table with 3 columns and 9 rows Directive Local Value Master Value mysql.allow_persistent On On mysql.default_host no value no value mysql.default_password no value no value mysql.default_port no value no value mysql.default_socket no value no value mysql.default_user no value no value mysql.max_links Unlimited Unlimited mysql.max_persistent Unlimited Unlimited table end interesting...seems to be pretty much the default install of all of it but All I can say for certainty is that if I uploaded your code onto my web host, it'd fail. So long as you're building this in a controlled environment and you know where it's going to go when it's live, then I guess you can exploit this to its full potential. i always fully test my code before i run it -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] re:[PHP] login problem fixed!!
Hello Andy, Thursday, March 25, 2004, 5:45:52 PM, you wrote: AB PHP Version 4.0.4pl1 Wow, that's an old version of PHP! It could be the cause of this, there's nothing in you phpinfo to give anything else away (i.e. it's identical to mine). -- Best regards, Richard Davey http://www.phpcommunity.org/wiki/296.html -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php