Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Critical - Security in php - 2 Clicks at same time - Duping

Status
Not open for further replies.

tcardoso

Programmer
Jan 31, 2005
56
PT
Hi,

Problem: Some folks in my site are clicking two buttons at same time to request opposite operations, for example in Firefox one account clicks remove the thing I had put to sell, at exact same time in IE other account clicks I want to buy the product (normally its a "hacker" running both accounts on his computer and synchronizing both clicks).

Result: The product is sold but remove to the original account too making a duplication of product (known as duping).

Solution:
1) Change some field to 1 in DB saying that IP is working, when a request come from same IP and the field is still at 1, he is trying to dup - Doesn't work most of the times.

2) Lock tables - How can I lock tables from php to mysql and not cause a huge lag on server because of waiting request. (not to mention I will have to be very careful cause of deadlocks)

3) Its there a way to make a synchronize around the critical piece of code with wait/notify like I can do with java?

Thanks
 
Hi,
To start with, why not use sessions and track the user by his session? In this case two different sessions will be created one for firefox and the other for IE..

--------------------------------------------------------------------------
I never set a goal because u never know whats going to happen tommorow.
 
Exacly. Well user are using two diferent account in two diferent browsers, so it will have diferent session id, I can only catch him by the IP. But how?
 
if it's two different session id's then surely it's two different shopping carts and the interaction is irrelevant. otherwise i'm not understanding your problem at all. can you rearticulate?
 
its not shopping carts, its a game, players buy items from one anothers.

So the same player create two diferent account (we need to authorize several account in same IP) and do that trick (sell and buy from himself at the same time).

But becoming more tecnical, PHP don't have any wait/notify possibily or other like it?

Thanks
 
so the issue is that a select count(*) (to determine 'credit' quantum is hitting the server at the same time as an update? so even if a table is locked by the update the select will still be able to read the table ?

so why not lock the tables before you run the select? if the tables won't lock then there is an active write operation and you should wait.

an alternative klidge might be to introduce a random delay in the count script (before you do the select).

Code:
usleep (mt_rand(1000,1000000));

that would increase the difficulty of timing the two actions to coincide.
 
The problem is that we have normally 200 players online, that start complaining when server takes more than 1 second to respond, our times are normally between 0,09 - 0,80 (Page generation time) and we do not want to pass it.

I think that there is some simple solution, but how can I order to lock/unlock a table from php?

Thanks for replying
 
You don't. You have to lock the item.

- Put the item on a "reserved" status (and therefore not selectable anymore by anyone else once it is in a "shopping cart"). When the user logs out or cleans his shopping cart, remove the reserved statuses for that user.

Always check your data against the live situation. If someone can mess with your site that way, you underestimate your users. Learn from them. Think as someone who wants to abuse your site.



+++ Despite being wrong in every important aspect, that is a very good analogy +++
Hex (in Darwin's Watch)
 
Code:
mysql_query('LOCK TABLE tablename');
 
Ok. I'll post this in here and in MySQL forum.

If I do:

Code:
1) mysql_query('LOCK TABLE tablename');
2) mysql_query('SELECT * from tablename where condition=0');
3) if (cond) {
4)  mysql_query('UPDATE tablename SET condition=1 WHERE condition=0');
5) }
6) mysql_query('UNLOCK TABLE tablename');

What happens when another process arrives on 1 and tablename is already locked it wait until the table is unlocked?

Imagine something go very wrong and the code its interrupted in 3) for example, the table will stay locked. How will I solve that/How can I implicity release all locks?

Thanks
 
you need to use a write lock so append WRITE to your lock query.

i am not sure what the mysql c library reports in the event of a prior lock. i believe that the process waits an amount of time and then reports an error if tables are still locked. therefore you might want to put a loop or a try{} around the lock.

the lock is implicitly released when the thread breaks. but nevertheless explicit unlocking is a good practice to get into.

instead of locking, could you use a conditional update?

Code:
update tablename
set condition=1
where 
condition = 0
and
0 < (select count(*) from tablename where userid = 54)

 
Hi again,

Using lock tables `tablename` and unlock at the end it still allows duping :| I don't know why.

Using Write at the end of lock tables `tablename` it start generating errors on other queries (even if they have nothing to do with table `tablename`.

I really apreciatte some help, because from what I can see there are a lot of sites suferring from this.

Thanks
 
you need the write lock. otherwise reads will still be possible.

fix the problems caused by your other queries, or pursue one of the other potential solutions you have been given. personally i think a short sleep for a random period might fix the issue for you, as then your users will not be able to time their actions.

you might also question the mysql forum; they may have a different approach.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top