how to get the old session? - php

I have a post form with captcha based on session for example the code know is Ujkd9 after refreshing the code become Hi8P4 .
And this is the problem. If someone post the form the captcha code of the input become old, how to get the old session ?

Well you can't, but you could save the older session into another session key creating a copy of that session, by example :
$_SESSION['session_copy'] = $_SESSION['current'];

I'm assuming your captcha code is being made on the fly and output via some image making in PHP. Your problem is that once you make the image and output it, you have no way to figure out what the CAPTCHA value actually is?
Since I have absolutely no knowledge of what your application structure, or database looks like, I can give you recommendations based on what I would do:
If I can assume that your PHP script looks something like this:
$captcha_string = make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
In layman's terms, you are going to need to store that somewhere. But Where? Now, I want it kept in mind that I've never particularly worked with Captcha directly, so I'm not 100% on what the "best practices" are, and I also don't know what you're doing, so these are probably going to be vague answers for a vague question. There are roughly 3 options, the way I see it.
1. Database Storage
Realistically, I would probably use a database as a first go-to. In my database I would have a table named captcha, with the following definition:
CREATE TABLE captcha (captcha_id int unique not null auto_increment, session_id VARCHAR(100) NOT NULL, captcha_string VARCHAR(6) NOT NULL)
Note: I don't know what length the session_id() function will return, and I am currently unable to check. If you know how long the session id is, change the length on session_id to match. Similarly for captcha_string I don't know how many letters your captcha will have. Change the definition to fit your uses.
What you are going to do, in words is:
Query the database with the current session_id to see if a captcha image exists.
set the information in a variable, I am using $captcha_data
If $captcha_data is populated with information, use its captcha string, otherwise, create a new on and store it.
Note that for this example, I assume that your database connection, whatever type it is, sits in an object named $db I am using no particular type of database, just methods I use in my own database class. The definitions would look similar for yours, but probably not exact.
$session_id = session_id();
$sql = "SELECT * FROM captcha WHERE session_id='".mysqli_real_escape_string($session_id)."'";
$result = $db->query($sql);
if($result!==false){
$captcha_data = $db->fetchrow($result);
}
$db->free_result($result);
$captcha_string = (isset($captcha_data['captcha_string'])) ? $captcha_data['captcha_string'] : make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
if(!isset($captcha_data['captcha_id'])){
$sql = "INSERT INTO captcha (session_id, captcha_string) VALUES('".mysqli_real_escape_string($session_id)."','".mysqli_real_escape_string($captcha_string)."')";
$db->query($sql);//You should check that this query is successful in your code, but for brevity I am skipping it.
}
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
Now keep in mind, I would probably add a date or time column to the captcha data so that I could delete values from accounts that haven't been used in some months, just to keep size down, but that's something I leave to you.
2. $_SESSION Storage
I can't say I recommend this option. It's effectively the same as my previous answer, just without the database interactions.
In words, we are doing the following:
Checking if the $_SESSION['captcha_id'] value is set, if so, use it. If not, create it.
This code is going to look very odd, so I recommend looking up Ternary Operators
//Assuming your session_start() is at the top of the page
$captcha_id = $_SESSION['captcha_id'] = (isset($_SESSION['captcha_id'])) ? $_SESSION['captcha_id'] : make_hash();
make_captcha_image($captcha_string);
3. File System Storage
I'd like to say that if this is the option you're choosing you've got some life decisions to make. This should not be used. Ever. Seriously.
That being said, the basic premise here is
See if a file with the current session_id exists.
if it does, read it's contents and use them as the hash for the image
else, create a new hash, create and populate the data in the file.
How that looks in Code:
$session_id = session_id();
if(file_exists('temp/'.$session_id.'.php')){
$captcha_string = $captcha_data = file_get_contents('temp/'.$session_id.'.php');
}else{
$captcha_string = hash();
file_put_contents('temp/'.$session_id.'.php',$captcha_string);
}
make_captcha_image($captcha_string);
Just to reiterate: don't use this method. I am supplying this answer simply and solely because your question asked HOW to keep the captcha from changing.

Related

PHP setting var to only a portion of a string

I have a panel I'm making that will use session data from another forum to give it permissions. Basically when the user logs into our forum and the session and trust is created on the forum, they can click on the panel and the panel will check their browser cookie for the session id and trust id. It then takes that trust id and checks the forum's database for the user id associated with that trust. Then takes the session id and verifies that it belongs to that user id. The issue is that when I get the session id, the associated user id is part of a blob that i have to cast in order to get the data from the field. So I get a result like this:
('7c64c90413beb7d139c64ccc8b13380b',
'a:12:{s:12:"sessionStart";i:1454075264;s:2:"ip";s:4:"b???";s:11:"sessionCsrf";s:16:"-2Yx13nBLdstUj4H";
s:7:"user_id";i:20;
s:13:"password_date";i:1453353041;s:16:"previousActivity";i:1454072099;s:13:"trophyChecked";b:1;s:16:"promotionChecked";b:1;s:16:"dismissedNotices";a:0:{}s:15:"lastNoticeReset";i:0;s:13:"canAdminUsers";b:1;s:20:"userModerationCounts";a:2:{s:5:"total";i:0;s:13:"lastBuildDate";i:1454075264;}}'),
I know there is a lot there, but I singled out the part that matters to me. The first column returned is the session id, which im using to verify the user id, but the user id is in the middle of that all that crap in the second column. So you can see where I single out the definition, what I want to do is just assign that "20" after "user_id;i:" to a variable and discard the rest. I'm sure this is simply done, but at this point I think I'm just nuking it out and spinning wheels. I was thinking explode, but the structure of that data seems like that's not an option.
That data is simply the result of a PHP serialize() call. You can pass it to unserialize(), which will provide you with an array containing the values.
<?php
$str = 'a:12:{s:12:"sessionStart"…etc…etc…i:1454075264;}}';
$arr = unserialize($str);
var_dump($arr['user_id']);
In case you’re trying to extract the value from within MySQL alone, for some reason I’ve done something similar with an awful query containing lots of nested SUBSTR() and LOCATE() just two weeks ago. I wouldn’t recommend it. Especially because in my case I was doing a one-off reporting query, while you’re trying to do authentication with it. People might try to use specially crafted cookies to circumvent your string extraction and gain illegitimate access.

Storing users 'following' during a PHP session

I have a simple followers/following system set up within my app.
What would be the best way to store a complete array of 'users following' during a session so that I don't have to query the database multiple times throughout.
To clarify: When a user logs in once they have been authorized I query the database, get a full list of users that the logged in user is following and ultimately store it as a JavaScript variable. This way throughout the site, as the user navigates around I can constantly check the following status against any other user they may come across.
This query is only performed once when the user loads the full page, while navigating around it is not repeated.
This works well for javascript generated content i.e user hovercards etc...
However I would like to store this array (of only userid's) in PHP itself so that I can prevent further queries to the following table while generating content server side that requires a 'follower/following' check to be performed.
What would be the best way to do this?
Please bare in mind that the results are cached in memcached but if I can avoid any lookups at all and have a consistent array to check against that would be great.
Thanks in advance
So let me get this right, you want to store this list so it isn't queried on each page?
First I would recommend you only perform this query on pages that need this data and second I would say that on these pages you don't try this.
Imagine a user stops following or starts following. Some complex cache calculator or event bubbler programmed into your own PHP app to purge the foreign session of data (which is bad, the user has access to data that is not their own, a session infact) could be tiedious with security and performance.
The better thing to do is to perform the query again for each new page. This would be much easier, probably more performant and wouldn't be micro-optimising.
Edit
If you are picking out 10k rows on one page then you might be doing something wrong. You might be looking at it from the wrong perspective.
Store it in the session variable.
http://php.about.com/od/advancedphp/ss/php_sessions.htm
https://www.google.se/search?q=learning+sessions+php
UPDATE
Store the current user in a session and add it to the queries you are already doing to fetch the popup information and add that it tests if the popups person follows the current user.
The two ways that come to mind would be to just write joins with well placed indexes each time, which you've said you don't want to do, and just a simple array in the session, which would probably look something like this:
if (!isset($_SESSION['following']) {
$following = $user->getFollowingIds(); //some query in here to get an array of ids
$_SESSION['following'] = $following;
$_SESSION['following_str'] = implode(',', $following);
}
Then whenever you want to pull all of the statuses for the people that $user is following you can write a query, something like this:
$query('SELECT status.* FROM status WHERE user_id IN (' . $_SESSION['following_str'] . ')'); //not sanitized or safe but you get the idea

How do I use PHP sessions and implement basic ACLs?

I have been Googling session variables. As I understand it, I can use them to capture such things as username and other data.
I would like to be able to use the data in order to store the username of the last person to change the record of a particular field. Additionally, I would like to be able to limit what a particular user sees on the site. For instance, if a user generates a work order I would like that user to be limited to seeing only the work orders he/she creates and no one else's.
I'm very new at all of this and I don't have a enough understanding to even write some code you might correct for me. How can I send the data stored in the session variable as $_GET or $_POST? If I have it in that format I can use it in the query (I think).
I have a table called "work_orders" with a field called "updated_by". I would like to be able to store the ID of the last person who updated the record.
I would also like to add privileges to the work orders so that users can only view records created by particular users.
This is a project I undertook in my first year web design class. In the class are some students who think it is funny to see how much damage they can do to the work of others. This is the reason I would like to be able to limit them to accessing only the work orders they generate.
You might want to start by reading or watching a video tutorial that will help you better understand how and when to use session variables. The data that you store in the session won't stick around forever, so you will need to store most information in a database.
Here is what most people do: Once the user signs into the application, you put their user id into the session. This way, you know who they are. The server uses a cookie to make this bit of magic happen and when the user closes their browser, the server will forget who they are and the session data will be lost. So, in this example, the session is just keeping track of who the user is.
To store information about who last edited a field, you will probably want to use a database to store that information. There is no use in storing that information in a session variable.
You seem to be mixing your questions here.
Firstly, where is your database? If it were - for instance - MySQl, then you need to add an extra column to the work order table (and others. Personally, I like to add timestamp column to, for auditing porpoises) .
I prefer POST over GET because 1) it can hold more data and 2) it's not so easy for the user to tamper with.
So, if you have a form with an input field declared
<form>
Name:
(see http://www.w3schools.com/html/html_forms.asp)
You can access $_POST['user_name'] e.g
$sql = 'INSERT INTO work_order_table (user_name, ... <other column names>) VALUES($_POST['user_name'], .. <other values>)
I woudl recommend you to get a good book (cheap enough second had) or online tutorial and work your way through.
Pleas let me know if I missed anything or if anything is not clear. Good luck!
Since you are concerend about school kids screwing with your datbase
1) google for how to make MySql more secure
2) hint this will involve prepared staments
3) use POST, rather than get, so that you have urls like http://192.1.68.1.1/application rather than http://192.1.68.1.1/application?user=smith which tempt users to muck around with the URl "just to see what happens" (probably more of a danger than SQL injection at school level, but ... you never know
4) hit the libbrary for soemthign like O'Reilly's PHP & MySql for Dummies in 24 hours for complete idiot beginners - or find a god online tutorial
5) "I would like to be able to limit that particular user to viewing only the work orders they generated" READ up on WHERE in SQL SELECT
6) change the MySql root password - or even add anew user with root-like access then delete root
7) make sure that no student has acess to the server, lest they look at the PHP and see your MySql user & password

Session not incrementing correctly

I've been working on a little project that has gotten me turned on and off regarding mood. The problem which I've been having all from the start before I remade the application is that I try to increment a session called 'Score', but for some reason it won't increment. At a time I managed to get this working, but in the little time it did I didn't manage to find the root of the problem.
The application is just a simple word repeater/practicer. I have wordlists in .txt format which the application picks up, cuts out the lines and gives each word it's own session. Then it picks a random word and shows it to the user. If the word (array index) has already been used, it will be in an "used" array and cannot be chosen again.
When the user is presented a word, he is to type in the correct corresponding english (phonetic) word. After submitting the script will check if the POST value given corresponds with the answer stored in a session for that word.
Now, there is a session called 'Score'. This session is not changed unless User's Answer == Session's Answer (which is tested to work correctly). However, when those two answers are the same, the session does not increase. I have tried to use ++;, +1; and += 1;, none of which seems to be working. Also, I made the form submit to an external file to try and lessen the pain to see logic, in case you wondered.
I fail to see where I might have missed the logic and would be very grateful for any help as this project started off as something fun but has now just become a hassle:
Wordlists are structured like this: Cyrillic(RU) | Phonetic(RU) | English(answer).
HTML (index.php): http://pastebin.com/3ePLtzuj
PHP (engine.php): http://pastebin.com/pyXR2U2s
POST->PHP (wordcheck.php): http://pastebin.com/ZZxgkHkJ
wordcheck.php: check if $answer == $result is really true: var_dump($answer == $result);
your engine.php isn't included in your wordcheck.php if that does matter
check the existence of your session vars, before using them - like: $wordNum = isset($_SESSION['wordNum']) ? $_SESSION['wordNum'] : 0;

How do i make $_GET more secure.?

I am using the get method to perform some operation like, approve, markasspam, delete, for commenting system. i know it is highly insecure to go this way but i cannot help it out. because the reason for using $_GET method is to perform the operation within the page itself using PHP_SELF, and FYI i am using the post method using checkbox to perform the operation too.
now for making it bit secure i want to randomize the number or generate the hash or something and then compare it, get the id and perform the operation
my current code is somewhat like this.
<?php
if($approve == 1 )
{
?>
Unapprove
<?php
} else
{
?>
Approve
<?php
}
?>
| Spam
| <a class="edit-comments" href="edit-comments.php?id=<?php echo $id; ?>">Edit</a>
| Delete
and i perform the operation using this code..
if(isset($_GET['approve'])) {
$id = intval($_GET['approve']);
$query = "UPDATE comments SET approve = '0' WHERE id = '$id'";
$result = mysql_query($query);
}
if(isset($_GET['unapprove'])) {
$id = intval($_GET['unapprove']);
$query = "UPDATE comments SET approve = '1' WHERE id = '$id'";
$result = mysql_query($query);
}
if(isset($_GET['delete'])) {
$id = intval($_GET['delete']);
$query = "DELETE FROM comments WHERE id = '$id'";
$result = mysql_query($query);
}
if(isset($_GET['spam'])) {
$id = intval($_GET['spam']);
$query = "UPDATE comments SET spam = '1' WHERE id = '$id'";
$result = mysql_query($query);
}
instead of using approve or unapprove or delete or spam, i want to randomize or hash that words and want it as lengthy as possible and then perform the operation.
how do i do it? what is your take on this?
EDIT: Please Note Only the
Authenticated User i.e Admin will be
able to perform this operation. even
though it pass through authentication
system i want to add more security
even for admin. to avoid experiments
or accident
the code is not exact it is just the sample to make you understand what i want to achieve.
Whether you use GET or POST parameters here doesn't matter much in this context - what the script needs first is some sort of authentication. (After that is done, you can go into security details where GET is slightly less secure than POST - see the comments for details.)
I'd say you have two options:
Protecting the entire script using .htaccess - no changes needed to the script itself
Introducing PHP side user authentication and perform the operations only if a logged in user makes the request. Needs fundamental changes to the script but is most flexible.
Re your edit:
It turns out your script is already protected. In that case I assume you are uncomfortable with incremental ID numbers turning up in the URLs, getting cached in the browser etc. etc. The usual solution to that is to generate a random key for each comment when it is created (in addition to the incremental ID). That key gets stored in a separate column (don't forget to add an index) and you'd match against that.
A step even further would be to create temporary hashes for every action, which is the ultimate protection against a number of outside attacks.
Re your edit about using one-time hashes:
I've never implemented one-time hashes in an admin interface yet so I have no experience with this, but I imagine that a very simple implementation would store action hashes in a separate table with the columns hash, record and action. Whenever your tool lists a number of records and outputs "delete / approve / unapprove" links, it would generate three record in the hash table for each comment: One for delete, one for approve, one for unapprove. The "delete / approve /unapprove" links would then, instead of the record ID and command, get the correct hash as the only parameter.
Add a time-out function for unused hashes (plus delete any hashes that were actually used) and you're done.
You can do it that way, the $_GET is not the unsecure thing in your code. The unsecurity comes from you not checking wether the user is e.g. authorized to delete comments.
In your current code, anyone can delete anything at anytime and as often as they want.
If you have a wrapping code that ensures the if-statements postet by you are not executed if enter good reason here, then it's okay.
But you should try verifying, that the content of the parameters are really integers instead of just int_val'ing them and using them directly on the database.
On your edit
You should check your parameter is really an int. intval("test") will also return an integer, mostly 0.
You might consider regex for that, to verify the string only consists of numbers: preg_match('/[0-9]+/', $_GET['id']);
If so, you can perform the action.
You shouldn't use GET for any operations that change data on server. NEVER. You use it only to get data.
If you can't use forms for operation buttons (because there is another form outside them) you should consider this design:
You use AJAX to perform POST requests to your server
In javascript-disabled environments you use GET links like user.php?action=delete, which shows you very simple form on a separate page. The header in the form asks: "Are you sure you want to delete user X?" and it has two buttons: 1) "Yes" - that submits POST request to operation script, 2) "No" - which sends user back to the page where he has been

Categories