Remove manual challenge from google reCaptcha v2 - javascript

The v2 reCaptcha has some dramatic improvements over previous iterations. When first implemented (using PHP verification btw) all it asked from my users was to check a box. Then after a few form submissions, it asked for a user to identify some images, then after a few more form submissions it asks the user to verify multiple image challenges.
Does anyone know of a way to completely turn off/ disable manual image challenges in the google recaptcha API? i.e. I want them to ONLY check the JS checkbox - like the first few times the form was completed.
I know it kind of defeats the purpose, but I'm prepared to deal with a little bit of spam if traded for a much better user experience.
I've tried:
turning off the js by adding https://www.google.com/recaptcha/api.js?manual_challenge=false (dug up the line from some old API settings)
https://www.google.com/recaptcha/api.js?fallback=false (alternative 'true' just forces a non JS version)
https://www.google.com/recaptcha/api.js?data-type=none (a shot in the dark based on their display options)
I am assuming google monitors the implementation and changes the UI intelligently. In my instance many requests from the same IP address looks like a bot and therefore requires better verification. However, it is just a single user re-submitting the same form a number of times. What I'd like to do is override this to use the minimum security always.

Google's reCaptcha assumes that each time you're challenging someone, you suspect that they're a bot, so if they have already passed a challenge, the next challenge gets progressively harder.
Thus, only challenge someone when you think they might be a bot, such as the first time they submit the form, or if they're not authenticated to your site. Once Google tells you that the user is safe, trust them unless/until you have reason to suspect that user again.
The PHP $_SESSION superglobal is probably your best bet, but as with all sessions, be certain that you're following best practices (session name fingerprinting, token entropy, session fixation attacks, mixing insecure and TLS sessions, etc.)
The way I would handle it is, when a user first successfully passes a CAPTCHA challenge, do not challenge them again.
The example below is based on the code provided by Google in their example: https://github.com/google/recaptcha/blob/master/examples/example-captcha.php
<?php
if (empty($_SESSION['isCaptchaVerified'])) {
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) {
// verified!
$_SESSION['isCaptchaVerified'] = true;
} else {
$errors = $resp->getErrorCodes();
}
}
...
?>
<form action="/" method="post">
...
<?php if (empty($_SESSION['isCaptchaVerified'])) { ?>
<script type="text/javascript"
src="https://www.google.com/recaptcha/api.js?hl=<?php echo $lang; ?>">
</script>
<?php } ?>
</form>
This will:
Check if the user has passed a challenge before
Present the challenge if $_SESSION['isCaptchaVerified'] is not set or falsey
Not present any challenge if $_SESSION['isCaptchaVerified'] is truish
(See the PHP manual entry on empty() for what constitutes truish and falsey in this context).

Go to your admin console in google where you set up recaptcha for the site. Click on advanced settings, reduce the security preference to the least.
Solved

Related

What can be changed by user on web? (eg. $_SESSION, JS code)

I would like to know what can and what can not be changed by user related to Web Development.
Mainly if users can change variables in $_SESSION.
But it would be nice to know if some techniques that seem secure are actually not.
Another example would be user changing code in JS Classes etc.
I am sorry if this question seems too trivial to someone. Studied Web Development for 2 years and would like to learn something new.
Here is a example of code where I am not sure if user can change his $_SESSION['group']
public function login() {
if(isset($_POST['login_submit'])) {
if(isset($_POST['username']) and isset($_POST['password'])) {
// Fetching user data
$stmt = $this->conn->prepare('SELECT Password FROM TB_Users WHERE Username = ?');
$stmt->execute([$_POST['username']]);
$user = $stmt->fetch();
//-----------------------
// Password Verification
if(password_verify($_POST['password'], $user['Password'])) {
//-----------------------
// Fetching Group of user so it can be used later to fetch Permissions
$stmt = $this->conn->prepare('SELECT TB_userGroups_ID FROM TB_Users WHERE Username = ?');
$stmt->execute([$_POST['username']]);
$UserGroup = $stmt->fetch();
$_SESSION['group'] = $UserGroup['TB_userGroups_ID'];
//-----------------------
// Sending user back from Login page to Main/Index page
header("Location: ../index.php");
exit();
//-----------------------
}
}
}
Many thanks for any help or redirection to sources.
If by user you mean visitors to the website and not developers (just making sure), then no they cannot unilaterally change anything in $_SESSION since those values only exist on the server. The user only has a cookie on their end that the server uses to recognize which collection of $_SESSION variables belong to them. The developer is responsible for making sure that what goes into the $_SESSION is controlled. In the example you have here, the only way $_SESSION gets changed is based on what is retrieved from the database, so assuming that content is safe, then it is protected.
My only recommendation would be to get rid of your isset($_POST['var']) stuff and replace it with filter_input(). You can use this to retrieve values from $_POST and also sanitize them. When called, you can expect null or false for missing or invalid content, so it's a little easier to control validation vs empty values. Sample:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
Full docs on that here https://www.php.net/manual/en/function.filter-input.php
Be sure to familiarize yourself with the filter flags. FILTER_SANITIZE_STRING for instance is not a great one for passwords.
Some other things to consider:
Make sure your session cookies are flagged with HTTPOnly and Secure and if on PHP7+ also set SameSite flag to strict. HTTPOnly prevents javascript from being able to modify the cookie. These settings are in php.ini.
Make sure your users are protected from XSS where someone could access their session through malicious code injected into your site (or perhaps a completely external site). These headers can be set in an .htaccess or in a host/vhost configuration file.
Ensure that your encryption policy for passwords meets basic requirements including secure encryption methods and salts. In general you shouldn't have to retrieve a password from the database; you should be able to salt and encrypt the provided password one way and change your query to simply count the number of rows matching username and the encrypted password. This way the secured password in the database never exists on the web server (even in memory).

How to deal with the captcha when doing Web Scraping in Puppeteer?

I'm using Puppeteer for Web Scraping and I have just noticed that sometimes, the website I'm trying to scrape asks for a captcha due to the amount of visits I'm doing from my computer. The captcha form looks like this one:
So, I would need help about how to handle this. I have been thinking about sending the captcha form to the client-side since I use Express and EJS in order to send the values to my index website, but I don't know if Puppeteer can send something like that.
Any ideas?
This is a reCAPTCHA (version 2, check out demos here), which is shown to you as the owner of the page does not want you to automatically crawl the page.
Your options are the following:
Option 1: Stop crawling or try to use an official API
As the owner of the page does not want you to crawl that page, you could simply respect that decision and stop crawling. Maybe there is a documented API that you can use.
Option 2: Automate/Outsource the captcha solving
There is an entire industry which has people (often in developing countries) filling out captchas for other people's bots. I will not link to any particular site, but you can check out the other answer from Md. Abu Taher for more information on the topic or search for captcha solver.
Option 3: Solve the captcha yourself
For this, let me explain how reCAPTCHA works and what happens when you visit a page using it.
How reCAPTCHA (v2) works
Each page has an ID, which you can check by looking at the source code, example:
<div class="g-recaptcha form-field" data-sitekey="ID_OF_THE_WEBSITE_LONG_RANDOM_STRING"></div>
When the reCAPTCHA code is loaded it will add a response textarea to the form with no value. It will look like this:
<textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="... display: none;"></textarea>
After you solved the challenge, reCAPTCHA will add a very long string to this text field (which can then later be checked by the server/reCAPTCHA service in the backend) when the form is submitted.
How to solve the captcha yourself
By copying the value of the textarea field you can transfer the "solved challenge" from one browser to another (this is also what the solving services to for you). The full process looks like this:
Detect if the page uses reCAPTCHA (e.g. check for .g-recaptcha) in the "crawling" browser
Open a second browser in non-headless mode with the same URL
Solve the captcha yourself
Read the value from: document.querySelector('#g-recaptcha-response').value
Put that value into the first browser: document.querySelector('#g-recaptcha-response').value = '...'
Submit the form
Further information/reading
There is not much public information from Google how exactly reCAPTCHA works as this is a cat-and-mouse game between bot creators and Google detection algorithms, but there are some resources online with more information:
Official docs from Google: Obviously, they just explain the basics and not how it works "in the back"
InsideReCaptcha: This is a project from 2014 which tries to "reverse-engineer" reCAPTCHA. Although this is quite old, there is still a lot of useful information on the page.
Another question on stackoverflow: This question contains some useful information about reCAPTCHA, but also many speculative (and very likely) outdated approaches on how to fool a reCAPTCHA.
You should use combination of following:
Use an API if the target website provides that. It's the most legal way.
Increase wait time between scraping request, do not send mass request to the server.
Change/rotate IP frequently.
Change user agent, browser viewport size and fingerprint.
Use third party solutions for captcha.
Resolve the captcha by yourself, check the answer by Thomas Dondorf. Basically you need to wait for the captcha to appear on another browser, solve it from there. Third party solutions does this for you.
Disclaimer: Do not use anti-captcha plugins/services to misuse resources. Resources are expensive.
Basically the idea is to use anti-captcha services like (2captcha) to deal with persisting recaptcha.
You can use this plugin called puppeteer-extra-plugin-recaptcha by berstend.
// puppeteer-extra is a drop-in replacement for puppeteer,
// it augments the installed puppeteer with plugin functionality
const puppeteer = require('puppeteer-extra')
// add recaptcha plugin and provide it your 2captcha token
// 2captcha is the builtin solution provider but others work as well.
const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha')
puppeteer.use(
RecaptchaPlugin({
provider: { id: '2captcha', token: 'XXXXXXX' },
visualFeedback: true // colorize reCAPTCHAs (violet = detected, green = solved)
})
)
Afterwards you can run the browser as usual. It will pick up any captcha on the page and attempt to resolve it. You have to find the submit button which varies from site to site if it exists.
// puppeteer usage as normal
puppeteer.launch({ headless: true }).then(async browser => {
const page = await browser.newPage()
await page.goto('https://www.google.com/recaptcha/api2/demo')
// That's it, a single line of code to solve reCAPTCHAs 🎉
await page.solveRecaptchas()
await Promise.all([
page.waitForNavigation(),
page.click(`#recaptcha-demo-submit`)
])
await page.screenshot({ path: 'response.png', fullPage: true })
await browser.close()
})
PS:
There are other plugins, even I made a very simple one because captcha is getting harder to solve even for a human like me. You can read the code here.
I am strongly not affiliated with 2Captcha or any other third party services mentioned above.
I had created my own solution which is similar to the other answer by Thomas Dondorf, but gave up soon since Captcha is getting more ridiculous and I do not have mental energy to resolve them.
Proxy servers can be used so that the destination site does not detect a load of responses from a single IP address.
(Translated into Google Translate)
I tried #Thomas Dondorf suggestion, but I think the problem with the steps described in "How to solve the captcha yourself" section is that the token of the CAPTCHA it's valid only one time.
I'll try to explain everything in detail below.
WHAT I'M USING
I'm using as first browser (the one that will not solve the captcha) Google Chrome, and as a second browser (the one where i solve the captcha and i take the token) Firefox.
STEPS
I manually solve the captcha on this site https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php
I type the following code document.querySelector('#g-recaptcha-response').value in the google chrome console, but I get an error (VM22:1 Uncaught TypeError: Cannot read property 'value' of null
at :1:48), so I just search the token by opening Elements in Google Chrome and searching g-recaptcha-response with CTRL+F
I copy the token of the recaptcha (here is an image to show where the token is, after the text highlighted in green)
I type the following code document.querySelector('#g-recaptcha-response').value = '...'in the firefox console, replacing the "..." with the recaptcha token just copied
I get the following error and, if you then click on the documentation linked, you'll read that the error is due to the fact that a token can be used only one time, and it has of course already been used for the CAPTCHA you just solved to obtain the token itself (so it seems that the only objective of the token it's to say that the CAPTCHA has already been solved, it seems a sort of defense measurement to prevent replay attacks, as said here in the official documentation of the recaptcha.

Prevent user to find password through Firebug/Chrome Dev Tools

For the passport input field:
<input type="text" required="" tabindex="2" class="std_textbox" placeholder="Enter your account password." id="pass" name="pass">
When the <input type="password"> is changed to <input type="text"> The password is revealed. This can be risky in systems which have saved passwords or generated from Password managers.
Can client side encryption be used in here? How can it be implemented?
Short answer: It can not be prevented, unfortunately. This is because all client-side code (JavaScript) is modifiable by the client itself - thus making a client-based security system vulnerable.
The only workable solution I can think of, is to store a hashed representation of the password, instead of the raw password. This will (if you disregard hash-bruteforce attacks) keep the raw password safe.
A hash is a representation of the original text, and is non-reversable. That is, the original string of characters can not be retrieved by any algorithm, using only the hash. Examples of hash' is MD5 and SHA. This technique is commonly used in routers, where password often is stored in the browser.
Clarification: Never store your passwords in plain-text, and if you want to adopt this technique of pre-entered password; the hashing and/or encryption must occur on server side.
I saw solutions in different answers. In all of them, it is just harder to see the password, but it does not prevent someone from seeing it.
Note: On client side JavaScript objects can be manipulated and inspected. In the solutions provided in other answers I could easily
access the password information.
As others stated, you cannot prevent the user from viewing the
password using developer tools on client side.
I could not think of a use case, but you mentioned automatic form filler and the Remember me option.
Automatic form filler, as far as I know are master password protected. They should be; I would not use one if I could not switch it on or off securely. In this case it is my responsibility to log out, whenever I am in situation of sharing a computer.
Remember me option, as often promoted by web sites, should only be used when it is your personal computer and you do not expect to share your device with another person. Don't use it or make sure no one else uses your account. Again, it is your responsibility.
Now, you still see a need to prevent such an attack. All I can come up with is the following:
There is no viable solution on client side. So your solution must work on server side.
On server side you can encrypt or hash the function. Please see this question for more details. I will discuss this further in the rest of this answer. You can opt for either solution, however implementation differs.
If you use encryption, then you can always decrypt.
That might help you in the following scenario: Keep the password always encrypted. They should always match. However, when the user wants to change his password it will be clear text. The user cannot type it in an encrypted form. You have to solve that. There are solutions. I am sure you get that.
If you use (encrypted) hashing, then it is very hard to crack. You cannot decrypt it.
This might help you in the following scenario: The server sends only the hashed version. This way no attacker can use this information. You need to design it accordingly, but I imagine you figure that out too.
Having said that, I really don't see an acceptable use case for your requirement.
Let me explain why. You want to prevent an attacker from seeing the password in case a user remembers the passwords or uses an automatic form filler. Well, if an attacker is able to access a user's computer he would be able to simply log in, why bother seeing the password?
There is a reason why companies like Google or Facebook did not bring
in a solution for your use case. The went another path and trying to
push for increased security by 2-factor authentication
If you can use that, do it. It does not solve the issue completely, but you can expect it to increase security. In particular it is harder for an attacker.
As it is clientside, there is no real way to prevent this. In terms of a security model: we can't trust the client. On the other hand, however, there is no real way to implement this differently without the use of a third party device.
If you're willing to go through the trouble of having a third party device assist in authentication: have the website generate and show a random seed, have the device ask for the seed and password to generate a hash, and authenticate on the site using the hash. Of course, the hash will still be visible if you use a web debugger, but at least there's no point in storing/reading it as the hash will differ for each session. This isn't completely secure either, by the way, as this method is prone to chosen plaintext attack.
Kudos if you're willing to go through all this trouble though. I suppose you could write an app for this to have a smartphone function as the third party device.
Absolutely not. You can't prevent the end user to manipulate the DOM from Developer tools or firebug.
Use of any client side trick can't prevent user to do that. Until or
unless the browser restrict user's from doing that.
I believe the issue you are facing is multiple people using the same computer, and if one user saves their password on your site, then any one else that visits the site on the same pc will be able to manipulate the field to reveal the password.
One way of preventing this from happening is to disable the auto-complete. autocomplete="off" Place this code in the input element and even if the password is saved, it shouldn't show up. <input autocomplete="off" type="text" required="" tabindex="2" class="std_textbox" placeholder="Enter your account password." id="pass" name="pass">
Pros You don't have to worry about users sharing computers, and passwords being revealed for the most part.
ConsUsers may think their passwords are saved (and they can still save passwords) but when they get to your site, it will not show up. NOTE This isn't the full-proof way of preventing users form manipulating the form and retrieving other users passwords.
As a side note, if the site does not refresh after entering a password and user name the web browser will not ask to save the password. For example, using an ajax call in stead of form submit.
You can use JavaScript to erase the text inside the password field when the page loads. A better style would be adding the field when the page loads with JavaScript like so:var x = document.createElement("INPUT"); x.setAttribute("type", "password");
An alternative to the autocomplete="off" autocomplete alternative It involves generating a name from the backend and using it as the name of the fields so that the autocomplete will never know where to put your users saved data
Well it is not possible with current technology. Like others stated, you still can inspect all the client side code and try to manipulate the DOM.
The other solution is to implement like banking login. Randomise the password sequence every time user login. For example if password length is 10, give user three password fields, ask the sequence of password eg. 3rd, 5th, 10th. This will change every time user try to login. And in the server side you compare them.
Note: I think you should avoid doing this as it will break basic browser functionality.
But if you insist, you could make it harder for someone to reveal the password by "delegating" the typing to another input field and populating the password field with random characters.
Below is an example of one way to do so. Keep in mind that by no means does it prevent someone from retrieving the password from the request body directly or if they find your 'hidden' delegate element.
!function() {
var passwordEl, delegateEl;
function syncPassword() {
passwordEl.value =
Array(delegateEl.value.length + 1).join('*');
}
function createDelegate() {
delegateEl = document.createElement('input');
delegateEl.style.position = 'absolute';
delegateEl.style.top = '-9999px';
delegateEl
.addEventListener('keyup', syncPassword, false);
document.body.appendChild(delegateEl);
}
window.addEventListener('load', function() {
passwordEl = document.getElementById('passwordId');
createDelegate();
// steal the focus from the password input
passwordEl.addEventListener('focus', function(e) {
e.preventDefault();
delegateEl.focus();
}, false);
syncPassword(); // clear if was auto completed
}, false);
}();
Now you have the option of re-filling your password input with the correct password on form submit, or simply have your server expect the password to arrive from the delegated field.
If you fancy, you could add the appropriate styling to the password field when the delegate field is focused and thus give the user the impression that they are still focused on the password field itself.
But don't.
As already said, having a password in an input element will let the user easily reveal password.
...And as #Elyasin asks, you really should let us know what your use-case is.
Being in the dark about your use-case, let's assume you have a website that users can subscribe to for a fee and you don't want multiple users sharing one person's login to get around paying your subscription fee.
You might use cookie authentication to check that a user is subscribed to your site.
When a new user subscribes, send them an email containing a link to a special registration page on your website.
When the user follows that link, place a cookie on the user's computer indicating they are a valid subscriber.
Create a landing page on your site. This landing page will read the cookie from the user's computer and authenticate that they are indeed a valid subscriber.
All other pages on your site must redirect users to the landing page if those users don't have the validating cookie.
Since un-subscribed users may be redirected to the landing page, you might offer to let them become subscribers on the landing page.
If a subscribed user's subscription has expired, you take the cookie off the (now unsubscribed) user's computer the next time they visit your site. Like any unsubscribed user, you redirect them to the landing page.
While it's true that cookies can be intercepted or stolen, it's usually beyond the casual user's ability to do so.
If you want more security using cookies, you can capture a user's IP address when they initially subscribe. Then you can verify that the user both has a validating cookie and also is accessing from the same IP address they originally subscribe from. Of course, this limits the subscribe to using only their original IP address to access your site.
You can use a simple Javascript code to store the password value in a variable onblur and then restore it onfoucs or/and onsubmit.
Look at the following demo code and its online demo here:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script>
password = '';
function setPasswordBack(){
showPassword();
}
function hidePassword(){
p = document.getElementById('pass');
password = p.value;
p.value = '*********';
}
function showPassword(){
p = document.getElementById('pass');
p.type= "password";
p.value = password;
}
</script>
</head>
<body>
<form action="" method="get" onsubmit="setPasswordBack()">
<input type="password" value="" name="password" id="pass" onblur="hidePassword()" onfocus="showPassword()" />
<input type="submit" />
</form>
</body>
</html>
It is clear that solution is JavaScript dependent solution, so in the case of disabling javascript, you may use noscript asking for JavaScript enabled browser.
Well, you can't.
But then again. There is one way of course to prevent user never seeing it using Developer console - never display the INPUT field which has the password.
The alternative would be to emulate the field's behaviour so that it seems to be there, but isn't. I have not found a technically sound solution yet how it could be done, but here is one example how it might be done: (updated) http://jsfiddle.net/858kef4h/
In this example, the idea is to create a DIV based pseudofield which looks like password INPUT and is listening keypresses from the user and saving the value to a JavaScript variable
<div class="pwField">
<div class="pwData"></div>
<div class="cursor"><div class="tfarea"></div></div>
</div>
This simple hack just has three state variables for password, focus state and the hidden textarea
var pw = "", bHasFocus = false, tfArea;
The "cursor" class is toggled on / off using JavaScript to emulate real cursor
setInterval( function() {
$(".cursor").toggleClass("blink");
},600);
When the div is clicked it creates a textarea at the place of the cursor and focuses to it.
$(".pwField").on("click", function() {
// enable cursor and create element if needed
$(".pwField").addClass("active");
if(tfArea) { // if already created, just focus to the field
tfArea.focus();
bHasFocus = true;
return;
}
tfArea = document.createElement("textarea");
tfArea.value="";
$(".tfarea").append(tfArea);
tfArea.focus();
bHasFocus = true;
$(tfArea).on("blur", function() {
// disable cursor and exit
$(".pwField").removeClass("active");
bHasFocus = false;
});
});
Then you can listen to keyup/keydown and record the values
$(document).keydown(function( ) {
if(!bHasFocus) return;
pw = tfArea.value;
// print asterisks
$(".pwData").html( asterisks( pw.length ) );
});
And when you are ready to login, the value is in the "pw" variable.
This dynamically created TEXTAREA may go unnoticed by the automatic password managers, because it is not the kind of INPUT -field the Password Managers are expecting to see.
The user which edits the field can naturally inspect the value of this element using the Chrome Developer tools, but the point here is, if the PW manager does not consider that field as a password -field it is not filling it with the password of the previous user.
I don't recommend using this, this was just made out of curiosity. The idea was to show that even though you can not prevent the user from seeing the elements, you may still be able hide the result from Password Managers. But like the old saying goes, "you can fool some of them some of the time, but not all of them all of the time".
The user experience is not the same as with standard input, but it could be improved. One problem is also that, even though you wanted to prevent the password to be shown, that may be what the users really want. They may want to user the Password Manager. But in this case you are out of luck anyway.
There may also be problems with the click, focus and blur with different browsers, they may not work with mobile devices as you expect. If this kind of hack is ever used, you should carefully tested. It could be used, if you know exactly what kind of browsers the users are using and you know they have JavaScript enabled.
EDIT: I tested the approach with some mobile devices and it seemed to somewhat work, but with iPad, and noticed that placing the hidden textarea will still create a visible cursor and change the zoom, so now the hidden textarea is placed inside the pseudocursor DIV and the zoom should follow it.
You can't, and you shouldn't. This is not a security issue you should be tackling on your website. It's up to the user to keep their passwords safe. If I have the ability to use the dev console or otherwise inject javascript on your page, no matter what you do the user's passwords will still be compromised.
If a user chooses to save their passwords in their browser, then it's up to them to prevent them from falling into wrong hands, and there's absolutely nothing you can do about it on your site. In fact, if you're using Chrome and have passwords saved, navigate to chrome://settings/passwords and click on some password fields.
Other answers talk about hashing passwords etc. That's something you should definitely do, but on your server. You could of course hash or encrypt a password before sending it to your server (and you really should too, using https), but that's a completely different issue.
The premise of this question is that the client computer is compromised and is being used by someone who should not have access. Assuming that a password manager is in use (such as Chrome's) which does not require a master password before each login form auto-fill, there is nothing you can do to prevent the attacker from gaining access to accounts.
You are trying to solve a problem at the application level when the access problem is deeper than that.
Suppose Bob forgets to log out of his computer. An attacker (Eve) stumbles upon his open Windows session and wants to gain access to his PayPal account. Bob uses a password manager for multiple accounts, including his Gmail, Paypal, and Reddit accounts. Suppose PayPal took application level precautions to prevent Eve from learning Bob's password from a password manager's auto-filling. Eve thinks she will only be able to have control of Bob's PayPal account for as long as it takes for Bob to return. But then, Eve notices PayPal's password reset link feature. Bob's email account is also compromised because his password for it is also in the password manager. With access to Bob's email account, Eve can reset any of Bob's passwords that she wants. She could maintain access by installing a keylogger on Bob's computer.
Bottom line, the security concerns you are trying to address are beyond your power to address (assuming a conventional username password model). Even without assuming anything about your application, Eve has physical access to Bob's computer, so she could compromise it in a multitude of ways.
If you make your users use two factor authentication (send them a code via text message via Twilio), make them carry around a hardware usb key, etc...you will increase security and avoid the password manager problem at hand.
But ultimately, you face a trade-off of security and usability. If Bob is too lazy/forgetful/apathetic/negligent to log out of his PC, no amount of JavaScript you write can save him.
Well , in 2019 there is a tricky way ..
you can generate forms with JavaScript / jQuery over a div
and you can put them on READ ONLY.
If the attacker will disable JavaScript then the gen code will not work then will not be any form at well...
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<title>Basic security for mr. Hacker</title>
</head>
<body>
<div id="ticketAF0122"></div><!-- it is assumed that id is generated every time !!! -->
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script>
$(document).ready(function(){
function readonly(){
$('div#ticketAF0122').html('My password<form method="post" action=""><input type="password" name="password"><input type="submit"></form>');
}
readonly()
$('div#ticketAF0122').bind("DOMSubtreeModified", function(){
readonly();
});
});
/*
Basicly you can load this part from an encoding external php file:
<script src="page.php?ticket=ticketAF0122">< /script>
and the php file generate something like:
$(document).ready(function(){
function readonly(){
$('div#ticketAF0122').html('My password<form method="post" action=""><input type="password" name="password"><input type="submit"></form>');
}
readonly()
$('div#ticketAF0122').bind("DOMSubtreeModified", function(){
readonly();
});
});
*/
</script>
</body>
</html>
i already check this on xampp /windows 10 with firefox and changing with the inspector from type="password" to type="text" the script will "repair" again the things
in EDGE works buggy : when with Inspector i modify that stuff then all form is strip then inserted above html document

Implementing a web page hit counter in 2013

I'm looking to implement a web page hit counter to let the server know what pages are being viewed where I'm trying to avoid sending the server repetitive 'user hits' by the same user, same page. (I'm not super concerned about them clearing their cache etc. and possibly getting counted again)
I've generally seen something like this:
<img src="/the-hit-counter?pageId=SOME_PAGE_ID" />
and then use a cookie to make sure the 'hit' doesn't get counted again.
But is there any reason to not use AJAX to notify the server other than the obvious "the user must have JavaScript enabled"? I'm guessing almost everyone that isn't wearing a tin-foil hat these days will have it enabled in their browser.
With AJAX and JavaScript I could do something like this and bring local storage into the mix and reduce some network bandwidth:
if (!amplify.store('SOME_PAGE_ID')) {
$.get('/the-hit-counter?pageId=SOME_PAGE_ID');
amplify.store('SOME_PAGE_ID', "");
}
What am I missing about the JavaScript approach?
I think the 2013 way to do this is to just sign up for Google Analytics, and paste its generated JavaScript into your site. Much easier than rolling your own solution, and you get a wealth of user data (demographics, locations, accurate user counts, etc.).

Javascript location.hostname Safe?

Lets say I have a php generated javasrcipt file that has the user's name, id number and email adress that is currently logged in. Would a simply document.location.href look up prevent remotes sites from determining the currently logged in user?
Would this be safe?
if(window.document.location.hostname == 'domain.com')
var user = {
name:'me',
id:234243,
email:'email#email.com'
};
else alert('Sorry you may not request this info cross sites.');
Initially it appears safe to me.
EDIT: I had initially thought this was obvious but I am using cookies to determine the currently logged in user. I am just trying to prevent cross domain access to the users info. For example if the if statement was removed malicious site A could embed the javascript file and access the users info. By adding the if statement the user js object should never appear. Cross site ajax isn't supported therefore only through javascript insertion could the malicious site attempt to determine the currently logged in user.
EDIT 2: Would checking my http_refer using php be safe? What if caching is also enabled for the client? For example if the user visits my site A where the user script is downloaded and then later visits site B malicious site would the script be cached, therefore bypassing the need for the server to check the user's http_refer?
You're basically saying "here's the keys to the bank vault, here's the guard's schedule, and here's the staff schedule. But hey, if you're not from the Acme Security Company, pretend I didn't give this to you".
"oh, sure, no problem, lemme just pretend to shred this note and go rent a large truck haul away your vault contents with"
You really just don't want to try something like this. Suppose I'm running an evil site; what do I do?
<script>
RegExp.prototype.test = function() { return true; };
</script>
<script src="http://yoursite.example.com/dynamicjs.php"></script>
<script>
alert("Look at the data I stole: " + user);
</script>
No, what you have there is not "safe" in that it will reveal those details to anyone requesting the HTML page containing that JavaScript. All they have to do is look at the text (including script) returned by the server.
What it comes down to is this: Either you have authenticated the other end to your satisfaction, in which case you don't need the check in the JavaScript, or you haven't, in which case you don't want to output the details to the response at all. There's no purpose whatsoever to that client-side if statement. Try this: http://jsbin.com/aboze5 It'll say you can't request the data; then do a View Source, and note that you can see the data.
Instead, you need to check the origin of the request server-side and not output those details in the script at all if the origin of the request is not authenticated.
Update 1: Below you said:
I was specifically trying to determine if document.location.href could be falsified.
Yes, document.location can be falsified through shadowing the document symbol (although you might be able to detect that if you tried hard enough):
(function() {
var document; // Shadow the symbol
document = {
location: {
href: "http://example.com/foo.html"
}
};
alert("document.location.href = " + document.location.href);
})();
Live copy
Cross-domain checks must happen within the browser's internals, nothing at the level of your JavaScript code can do it securely and robustly.
But that really doesn't matter. Even if it couldn't be falsified, the quoted example code doesn't protect the data. By the time the client-side check is done, the data has already been sent to the client.
Update 2: You've added a note about checking the HTTP_REFERER (sic) header (yes, it really is misspelled). Sadly, no, you can't trust that. HTTP_REFERER can be spoofed, and separately it can be suppressed.
Off-topic: You're probably already doing this, but: When transferring personal details you've promised to keep confidential (I don't know whether you have, but hopefully so), use HTTPS (e.g., SSL). But it's important to remember that while HTTPS ensures that data cannot be read in transit, it does nothing to ensure that the origin of the request is authenticated. E.g., you know the conversation is secure (within reason and current practice), but you don't necessarily know who you're talking to. There's where authentication comes into it.

Categories