Related
I'm attempting to create a new page every time a form is submitted. It'll be an order status page- one that'll be updated periodically. Basically, I want the user to see a form confirmation page, and I want it to be permanent link (that they can visit later).
My first thought was using variables in the URL, like so:
http://www.example.org/member.php?id=123
And then calling the id using GET
echo $_GET['id'];
http://www.example.org/member.php would be a template, just waiting for the few details which are specific to the user.
Once I have this in place, I could use a simple if statement to check their order status.
For example,
if ($id === "user_id") {
echo "Your order is: Pending";
}
However, this seems like a bad idea, just for the security aspect of it. If someone else guesses a user ID, they can view their order status. Going off of that, here's my first question.
If the user ID is long enough, is this a secure practice?
Otherwise, what are some other methods of doing this? Creating a new page every time the form is submitted feels like a bad practice- people could spam it, and there's a possibility that someone could exploit this to create malicious pages on the site.
Any suggestions? Most major retail sites have order confirmation pages (think ebay.com)- how do they do it? Also, is my suggested URL format secure?
The most ideal scenario is you force users to login prior to submitting the form then provide them with a list of their past orders of which they can check the status providing the user_id of the order matches the id from the session of the logged in user. Give each order in the list a link like yoursite.com/orders/1 then query for an order with an id of one with a user_id matching the logged in users id to ensure they're the only ones that can view it.
If you don't want to have to do any of that and just provide a permanent link to the status page I'd save a long randomly generated string against the order and provide it to the user to check in the future, e.g
yoursite.com/orders/wUk1DhfxMh if you're using a framework with some routing
or yoursite.com/orders.php?code=wUk1DhfxMh if you're not.
Query the database to select the order with the matching code, ensure you prevent MySQL injection and sanitize the $_GET input.
Are you sure you need to make a new page?
You could just have a basic "confirm" page (ex. http://yoursite.com/order/confirm) which uses PHP sessions to create a customized confirm page–
Other than that, IF you make a new page, you should use ID's in the URL and ALSO check the session id. (ex. http://yoursite.com/order/confirm/ABsisnEALnsoSK?yyyy=xxxx) and then ALSO check if the user is logged in.
Lastly, cymath has a good example of async page-creation; although it isn't exactly what you are looking for.
EDIT: It is not page creation, it's like what I said before: one page with extra parameters in the url: a permanent link, just using PHP.
I understood that you are having some doubts about how to make the algorithm of your app, here's what i thought to this case:
Insert the order at your database, get the id of the insertion and give it to the user.
Set the page where the user will check the status to receive a $_GET['id'], check (SELECT) if this id exists in the database.
(if the user exists): get the information you need from the table
you store them. (FETCH_ASSOC or FETCH_OBJECT)
(if the user don't exist):show an error.
If you are experiencing some doubts about how to code CodeSchool is offering free trial on all courses this weekend.
If the user ID is long enough, is this a secure practice?
R: To improve the security of the transactions, try to understand/learn about PDO Class, i think it will get your code to next level if you aggregate some Good Practices and Design Patterns.
For more information, visit PHP's Documentation.
I need help.
We need to find a questionnaire in which the answer to the question (for example, telephone number) may not be the same for two users.
For Example:
Enter a phone number:
First the user enters a phone number: 123456789
And completes the survey.
The second user starts to question and answers the same phone number 123456789.
He receives an error message or a request to enter a different answer.
Or is there any easy implementation of this problem using php or javascript.
Maybe it is possible to implement with surveymonkey api.
I would be glad of any help or advice.
Google forms writes to a spreadsheet database, allows regular expression fields and attached scripts. Set the field to mach your required format, then validate the response with a script.
Your requirement is persistent storage. You will either require a database, such as MySQL, and use PHP to access it, or a third party application such as SurveyMonkey. However, I can't tell you the limitations of SurveyMonkey, you will have to check their documentation.
I realize that this late and this thread is limited but for others looking for same answer. Here is how I did exactly the same thing for one of my coworkers using Examinare Framework and Examinare Survey Tool.
First, create a html form that sends the phone number to a form.
Inside that PHP file call Examinare PHP Wrapper and check if a recipient has this phone number on their recipient profile.
https://developer.examinare.com/apidocs/listrecipientsbygroup/
A tip: And loop through it the results.
If the recipient not exist, create the recipient. Make sure you add a fake or real email to prevent getting an error.
https://developer.examinare.com/apidocs/addrecipient/
Mark the recipient as a active in the survey.
https://developer.examinare.com/apidocs/markrecipientstosurvey/
Redirect to the survey.
If you want the recipient to return to a certain path then add redirect_url variable to the url with a valid url.
Hope it helps you and future seakers.
Intro:
I am pretty inexperienced, but recently I have been trying to access some data from a website using Google Apps Scripts. However, to access the data, I must be logged into that website. There have actually been many posts about similar issues before, but none of them were very helpful until I came to this one: how to fetch a wordpress admin page using google apps script. The accepted answer gave a method for saving the cookies and sending them out again in the second request. I basically copied and pasted the code into my own GAS file. Since the problem in that post was logging into Wordpress, I tried that first, and it worked. I had to remove the if statement checking for the response code because 200 was being returned even when I entered the correct combo. I don't know if that was just an error in the post's code or what. In any case, I verified that the second request I made returned information as if I was logged in.
Details about specific site:
The actual website that I am trying to log onto has a some kind of weird hashing method that I haven't seen on any other login pages. When you click submit, the password changes to something really long before going to another page. The opening form tag looks like this:
<form action="/guardian/home.html" method="post" name="LoginForm" target="_top" id="LoginForm" onsubmit="doPCASLogin(this);">
As you can see, it has an "onsubmit" attribute, which I believe will just run "doPCASLogin(this);" when the form is submitted. I decided to play around with the page by just entering javascript into the address bar. What I found was that doing a command like this (after entering in my username and password):
javascript: document.forms[0].submit();
didn't work. So I dug around and found the function "doPCASLogin()" in a javascript file called "md5.js". I believe md5 is some kind of hash algorithm, but that doesn't really matter. The important part of "doPCASLogin()" is this:
function doPCASLogin(form) {
var originalpw = form.pw.value;
var b64pw = b64_md5(originalpw);
var hmac_md5pw = hex_hmac_md5(pskey, b64pw)
form.pw.value = hmac_md5pw;
form.dbpw.value = hex_hmac_md5(pskey, originalpw.toLowerCase())
if (form.ldappassword!=null) {
form.ldappassword.value = originalpw;
}
}
There is some other stuff as well, but I found that it didn't matter for my login. It is pretty obvious that this just runs the password through another function a few times using "pskey" (stored in a hidden input, different on each reload) as a key, and puts these in inputs on the original form ("dbpw" and "ldappassword" are hidden inputs, while "pw" is the visible password entry input). After it does this, it submits. I located this other "hex_hmac_md5()" function, which actually connects to a whole bunch of other functions to hash the password. Anyway, that doesn't matter, because I can just call the "hex_hmac_md5()" from the javascript I type in the address bar. This is the working code that I came up with, I just broke the line up for readability:
javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="hex_hmac_md5(pskey, b64_md5('password');)";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm']['dbpw'].value="hex_hmac_md5(pskey, 'password')";
document.forms['LoginForm'].submit();
Wherever you see "username" or "password", this just means that I entered my username and password in those spots, but obviously I have removed them. When I discovered that this worked, I wrote a small Chrome extension that will automatically log me in when I go to the website (the login process is weird so Chrome doesn't remember my username and password). That was nice, but it wasn't my end goal.
Dilemma:
After discovering all this about the hashing, I tried just putting in all these values into the HTTP payload in my GAS file, though I was skeptical that it would work. It didn't, and I suspect that is because the values are just being read as strings and the javascript is not actually being run. This would make sense, because running the actual javascript would probably be a security issue. However, why would it work in the address bar then? Just as a side note, I am getting a 200 response code back, and it also seems that a cookie is being sent back too, though it may not be valid. When I read the actual response, it is just the login page again.
I also considered trying to replicate the entire function in my own code after seeing this: How to programmatically log into a website?, but since "pskey" is different on each reload, I think the hashing would have to be done with the new key on the second UrlFetch. So even if I did copy all of the functions into my GAS file, I don't think I could successfully log on because I would need to know the "pskey" that will be generated for a particular request BEFORE actually sending the request, which would be impossible. The only way this would work is if I could somehow maintain one page somehow and read it before sending data, but I don't know how I would do this with GAS.
EDIT: I have found another input, named "contextData", which is the same as "pskey" when the page is loaded. However, if I login once and look at the POST request made using Chrome Developers tools, I can copy all the input values, including "contextData", and I can send another request a second time. Using javascript in the address bar, it looks like this:
javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="value in field that browser sent once";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm'['dbpw'].value="value in field that browser sent once";
document.forms['LoginForm'['contextData'].value="value in field that browser sent once";
document.forms['LoginForm'].submit();
I can sign into the website as many times as I want in this manner, no matter what "pskey" is, because I am submitting everything directly and no hashing is being done. However, this still doesn't work for me, so I'm kind of stuck. I should note that I have checked the other hidden input fields and I can still log in successfully with the javascript above even after clearing every input in the form.
QUESTIONS:
-was I correct in assuming that the code I was sending was being interpreted as a string?
-why is the new code below that I just recently wrote not working?
-for future reference, how would I use GAS to sign into a site like Google where a randomly generated string is sent in the login form, and must be sent back?
function getData() {
var loginURL = 'login page';
var dataURL = 'page with data';
var loginPayload = {
'account':'same as in previous code block',
'pw':"same as in previous code block",
'ldappassword':'same as in previous code block',
'dbpw':"same as in previous code block",
"contextData":"same as in previous code block",
};
var loginOptions = {'method':'post','payload':loginPayload,'followredirects':false};
var loginResponse = UrlFetchApp.fetch(loginURL,loginOptions);
var loginHeaders = loginResponse.getAllHeaders();
var cookie = [loginResponse.getAllHeaders()["Set-Cookie"]];
cookie[0] = cookie[0].split(";")[0];
cookie = cookie.join(";");
var dataHeaders = {'Cookie':cookie};
var dataOptions = {'method':'get','headers':dataHeaders};
var dataResponse = UrlFetchApp.fetch(dataURL,dataOptions);
Logger.log(dataResponse);
}
some kind of weird hashing method that I haven't seen on any other login pages
This login uses the well-known MD5 hashing algorithm from a base-64 encoded password (of note is that it uses the same password, but lowercased, for what seems like database access dbpw and has an option of sending the plaintext (!) version of the password for LDAP login).
know the "pskey" that will be generated for a particular request BEFORE actually sending the request, which would be impossible
pskey simply stores the key used in computing HMAC signature. There is nothing stopping you from hardcoding it, reading from disk, generating it or fetching from remote whenever and wherever you want (obviously, before the computation).
running the actual javascript would probably be a security issue
Although running untrusted JavaScript code is indeed a security issue, this is not what happened at all in your case. See next point for detailed explanation why. What you should've done, is to actually run the hashing functions (in 2020, Utilities service provides everything you need in that regard) before assigning them to loginPayload properties.
was I correct in assuming that the code I was sending was being interpreted as a string?
Everything you put in quotes (single or double) is treated as a sequence of characters. That's not how Google Apps Script works, this is how ECMAScript (on which it is based) is designed to work. In order to execute the functions "inside" the string, you need to use eval, but please never do that.
Now, in 2020 it took me some time to remember what javascript: protocol meant. This is the only reason why your code executed in the first place - you explicitly told the browser that what follows is JavaScript code to be executed. If someone sees this: please, don't use that ever again.
Google Apps Script is a server-side code and is not executed in the browser environment, therefore, even if you did use the protocol, it would have no effect because no evaluation took place.
why is the new code below that I just recently wrote not working?
Because of all the reasons explained above.
for future reference, how would I use GAS to sign into a site like Google where a randomly generated string is sent in the login form, and must be sent back?
If you are talking about the OAuth / OAuth2.0 authentication protocol, here is an officially endorsed library dedicated for exactly this purpose.
We have a problem with users double-clicking on buttons within our application to proceed from screen to screen.
We have implemented the ( onclick="this.disabled=true" ) on our buttons but we are convinced that it is not always sufficient to stop the fast-fingered double-click.
A simple example :-
Screen A has four input fields and a proceed button. When the proceed button is pressed, control is passed to server-side routine to validate info, set some session vars and call screen B.
What appears to happen occasionally is :-
On first click the server-side routine is called and begins validating info and setting session vars. Second-click takes control and again calls the server-side routine and begins validating info and setting session vars -> for us, the session vars are already set and this highlights the problem.
We have looked at tokens but don't think they will solve our problem.
We think that since every PHP application must be vulnerable to this double-click issue there has to be a standard method for resolving it but we have yet to find one.
If you have resolved this issue then we would be grateful if you would like to give us some insights into how we might overcome the problem.
* Thanks for the replies. Loic and Brian Nickel - hard to separate as both going for the token method via timestamp or GUID. We will have to go back and take another look at tokens. After discussion - as a preferred solution for us, we would go with the GUID token concept.
Since double click will basically submit the same form twice you can check the timestamp between two submits.
I'll take the example of stackoverflow because this site is awesome.
Let's say I vote this question up, server side, if my POST request is valid, then my POST request will be treated, and saved.
Then server side, before treating a request, they will check if this same form hasn't been posted in last few seconds (don't they?).
Anyway, my point is, give your forms a name, and when validated, put a timestamp in your users session so you can refuse their post of the same form given a defined amount of time.
Best of luck.
This is a very common problem with a fairly standard solution. Whenever you generate your form, you should generate a unique token like a GUID and stick it in SQL, redis, memcached, the session, or any short term persistent store you have. Stick it in a hidden field. You should be doing one token for each generated form.
When the form gets submitted, atomically check for and remove the token from the store. If it's there the form was submitted for the first time. If not, it's a duplicate.
For bonus points, instead of showing an error on the second submission, you can store the token with the successful result data and use it to render the same success page as you would have if they clicked once.
1) Put a for the eye hidden div (or other element) on z-top of button (opacity:0.01)
2) when once clicked (mousedown) remove div
or:
1) Remove click event when once clicked
I'm trying to figure out a good way to prevent bots from submitting my form, while keeping the process simple. I've read several great ideas, but I thought about adding a confirm option when the form is submitted. The user clicks submit and a Javascript confirm prompt pops up which requires user interaction.
Would this prevent bots or could a bot figure this out too easy? Below is the code and JSFIddle to demonstrate my idea:
JSFIDDLE
$('button').click(function () {
if(Confirm()) {
alert('Form submitted');
/* perform a $.post() to php */
}
else {
alert('Form not submitted');
}
});
function Confirm() {
var _question = confirm('Are you sure about this?');
var _response = (_question) ? true : false;
return _response;
}
This is one problem that a lot of people have encountered. As user166390 points out in the comments, the bot can just submit information directly to the server, bypassing the javascript (see simple utilities like cURL and Postman). Many bots are capable of consuming and interacting with the javascript now. Hari krishnan points out the use of captcha, the most prevalent and successful of which (to my knowledge) is reCaptcha. But captchas have their problems and are discouraged by the World-Wide Web compendium, mostly for reasons of ineffectiveness and inaccessibility.
And lest we forget, an attacker can always deploy human intelligence to defeat a captcha. There are stories of attackers paying for people to crack captchas for spamming purposes without the workers realizing they're participating in illegal activities. Amazon offers a service called Mechanical Turk that tackles things like this. Amazon would strenuously object if you were to use their service for malicious purposes, and it has the downside of costing money and creating a paper trail. However, there are more erhm providers out there who would harbor no such objections.
So what can you do?
My favorite mechanism is a hidden checkbox. Make it have a label like 'Do you agree to the terms and conditions of using our services?' perhaps even with a link to some serious looking terms. But you default it to unchecked and hide it through css: position it off page, put it in a container with a zero height or zero width, position a div over top of it with a higher z-index. Roll your own mechanism here and be creative.
The secret is that no human will see the checkbox, but most bots fill forms by inspecting the page and manipulating it directly, not through actual vision. Therefore, any form that comes in with that checkbox value set allows you to know it wasn't filled by a human. This technique is called a bot trap. The rule of thumb for the type of auto-form filling bots is that if a human has to intercede to overcome an individual site, then they've lost all the money (in the form of their time) they would have made by spreading their spam advertisements.
(The previous rule of thumb assumes you're protecting a forum or comment form. If actual money or personal information is on the line, then you need more security than just one heuristic. This is still security through obscurity, it just turns out that obscurity is enough to protect you from casual, scripted attacks. Don't deceive yourself into thinking this secures your website against all attacks.)
The other half of the secret is keeping it. Do not alter the response in any way if the box is checked. Show the same confirmation, thank you, or whatever message or page afterwards. That will prevent the bot from knowing it has been rejected.
I am also a fan of the timing method. You have to implement it entirely on the server side. Track the time the page was served in a persistent way (essentially the session) and compare it against the time the form submission comes in. This prevents forgery or even letting the bot know it's being timed - if you make the served time a part of the form or javascript, then you've let them know you're on to them, inviting a more sophisticated approach.
Again though, just silently discard the request while serving the same thank you page (or introduce a delay in responding to the spam form, if you want to be vindictive - this may not keep them from overwhelming your server and it may even let them overwhelm you faster, by keeping more connections open longer. At that point, you need a hardware solution, a firewall on a load balancer setup).
There are a lot of resources out there about delaying server responses to slow down attackers, frequently in the form of brute-force password attempts. This IT Security question looks like a good starting point.
Update regarding Captcha's
I had been thinking about updating this question for a while regarding the topic of computer vision and form submission. An article surfaced recently that pointed me to this blog post by Steve Hickson, a computer vision enthusiast. Snapchat (apparently some social media platform? I've never used it, feeling older every day...) launched a new captcha-like system where you have to identify pictures (cartoons, really) which contain a ghost. Steve proved that this doesn't verify squat about the submitter, because in typical fashion, computers are better and faster at identifying this simple type of image.
It's not hard to imagine extending a similar approach to other Captcha types. I did a search and found these links interesting as well:
Is reCaptcha broken?
Practical, non-image based Captchas
If we know CAPTCHA can be beat, why are we still using them?
Is there a true alternative to using CAPTCHA images?
How a trio of Hackers brought Google's reCaptcha to its knees - extra interesting because it is about the audio Captchas.
Oh, and we'd hardly be complete without an obligatory XKCD comic.
Today I successfully stopped a continuous spamming of my form. This method might not always work of course, but it was simple and worked well for this particular case.
I did the following:
I set the action property of the form to mustusejavascript.asp which just shows a message that the submission did not work and that the visitor must have javascript enabled.
I set the form's onsubmit property to a javascript function that sets the action property of the form to the real receiving page, like receivemessage.asp
The bot in question apparently does not handle javascript so I no longer see any spam from it. And for a human (who has javascript turned on) it works without any inconvenience or extra interaction at all. If the visitor has javascript turned off, he will get a clear message about that if he makes a submission.
Your code would not prevent bot submission but its not because of how your code is. The typical bot out there will more likely do an external/automated POST request to the URL (action attribute). The typical bots aren't rendering HTML, CSS, or JavaScript. They are reading the HTML and acting upon them, so any client logic will not be executed. For example, CURLing a URL will get the markup without loading or evaluating any JavaScript. One could create a simple script that looks for <form> and then does a CURL POST to that URL with the matching keys.
With that in mind, a server-side solution to prevent bot submission is necessary. Captcha + CSRF should be suffice. (http://en.wikipedia.org/wiki/Cross-site_request_forgery)
No Realy are you still thinking that Captcha or ReCap are Safe ?
Bots nowDays are smart and can easly recognise Letters on images Using OCR Tools (Search for it to understand)
I say the best way to protect your self from auto Form submitting is adding a hidden hash generated (and stored on the Session on your server of the current Client) every time you display the form for submitting !
That's all when the Bot or any Zombie submit the form you check if it the given hash equals the session stored Hash ;)
for more info Read about CSRF !
You could simply add captcha to your form. Since captchas will be different and also in images, bots cannot decode that. This is one of the most widely used security for all wesites...
you can not achieve your goal with javascript. because a client can parse your javascript and bypass your methods. You have to do validation on server side via captchas. the main idea is that you store a secret on the server side and validate the form submitted from the client with the secret on the server side.
You could measure the registration time offered no need to fill eternity to text boxes!
I ran across a form input validation that prevented programmatic input from registering.
My initial tactic was to grab the element and set it to the Option I wanted. I triggered focus on the input fields and simulated clicks to each element to get the drop downs to show up and then set the value firing the events for changing values. but when I tried to click save the inputs where not registered as having changed.
;failed automation attempt because window doesnt register changes.
;$iUse = _IEGetObjById($nIE,"InternalUseOnly_id")
;_IEAction($iUse,"focus")
;_IEAction($iUse,"click")
;_IEFormElementOptionSelect($iUse,1,1,"byIndex")
;$iEdit = _IEGetObjById($nIE,"canEdit_id")
;_IEAction($iEdit,"focus")
;_IEAction($iEdit,"click")
;_IEFormElementOptionSelect($iEdit,1,1,"byIndex")
;$iTalent = _IEGetObjById($nIE,"TalentReleaseFile_id")
;_IEAction($iTalent,"focus")
;_IEAction($iTalent,"click")
;_IEFormElementOptionSelect($iTalent,2,1,"byIndex")
;Sleep(1000)
;_IEAction(_IETagNameGetCollection($nIE,"button",1),"click")
This caused me to to rethink how input could be entered by directly manipulating the mouse's actions to simulate more selection with mouse type behavior. Needless to say I wont have to manualy upload images 1 by 1 to update product images for companies. used windows number before letters to have my script at end of the directory and when the image upload window pops up I have to use active accessibility to get the syslistview from the window and select the 2nd element which is a picture the 1st element is a folder. or the first element in a findfirstfile return only files call. I use the name to search for the item in a database of items and then access those items and update a few attributes after upload of images,then I move the file from that folder to a another folder so it doesn't get processed again and move onto the next first file in the list and loop until script name is found at the end of the update.
Just sharing how a lowly data entry person saves time, and fights all these evil form validation checks.
Regards.
This is a very short version that hasn't failed since it was implemented on my sites 4 years ago with added variances as needed over time. This can be built up with all the variables and if else statements that you require
function spamChk() {
var ent1 = document.MyForm.Email.value
var str1 = ent1.toLowerCase();
if (str1.includes("noreply")) {
document.MyForm.reset();
}
<input type="text" name="Email" oninput="spamChk()">
I had actually come here today to find out how to redirect particular spam bot IP addresses to H E L L .. just for fun
Great ideas.
I removed re-captcha a while back converted my contactform.html to contactform.asp and added this to the top (Obviously with some code in between to full-fill a few functions like sendmail, verify form filled out completely etc.).
<%
if Request.Form("Text") = 8 then
dothis
else
send them to google.com
end if
%>
On the form i stuck a basic text field with the name text so its just looks like anything not specifying what its for at all, I then stuck some text 2 lines above in red that states enter what 2 + 6 = in the box below to submit your request.