FAQ Topic - How can I prevent access to a web page by using javascript? (2010-05-09)

R

Ry Nohryb

Ry Nohryb :


Well done !

Now, what about the real password ? Shall I post it, or does anyone want
more time to try ?

How long is the other pwd :) ? I can test them @ 180 KHz on a single
Core2, in Chrome. But there's still the question of how to know when
to stop, if you hadn't given me the .substring(0,5) ==== "*****"
hint ?
 
R

Ry Nohryb

Ry Nohryb :

[...]
  var stat= document.getElementById('idStatus') ||
document.body.appendChild(document.createElement('pre'));
[...]

    stat.innerHTML= [n, "[ "+ vector+ " ]", key];

[...]

Any particular reason why you do it in a browser ? I would have gone
straight to standalone v8.

It's easier, much more convenient: you just navigate to the page,
press cmd-I, paste my code and hit enter...

And in Chrome, if you open a second tab and do the same but choosing a
different vector to start from (e.g. [31,31,31,31]), it will run in
parallel in the second core (if on a Core2). And if you've got 4
cores... open 4 tabs, and so on.
 
G

Garrett Smith

Bwig said:
Johannes said:
Bwig Zomberi :
[...]
So, the FAQ should say that while it is possible to do it on the
client-side (browser), it is not the recommended way. The web
application should be in control. Server-side code should authenticate
access. Sending encrypted content to unauthorised users would make the
content susceptible to brute-force and weakness attacks.

Encrypted strings is a different matter.

It is not possible to prevent access to publicly accessible resources,
such as attempted by scripts that do things like:

var pwd = prompt("enter password");
location.href= pwd + ".html";
 
R

Ry Nohryb

Ry Nohryb :


Suppose the very worst case : you know absolutely nothing about the
plaintext, except that it is supposed to be read and understood by humans..

What simple property would still quite decisively set it apart from the
decryption with a wrong key ?

No idea.
How could you test that property by program ?

No idea.

I'd need to know a way to validate decrypt(crypt, key).
Unless encrypt(decrypt(crypt, wrongKey), wrongkey) !== crypt, and,
encrypt(decrypt(crypt, theRightKey), theRightKey) === crypt.

BTW, the rate I told you (180KHz) was per 30 seconds, not per second.
 
M

Mike Duffy

Garrett Smith :




Quite. And of course, if *that* is what the author of the question
had in mind, a firm advice against it is appropriate.


Why? As long as the server does not yield a list of available pages, it
should work to restrict access to people that know the password.


Of course, you do not need javascript; just tell your friends to go to

http://what.ever.com/secret_xyz.html and don't tell anyone else.
 
E

Evertjan.

Mike Duffy wrote on 13 mei 2010 in comp.lang.javascript:
Why? As long as the server does not yield a list of available pages, it
should work to restrict access to people that know the password.

Because those "friends" are just like other people, they will bookmark the
result on a computer, that is accessable to someone else, who will then use
that url as a hyperlink on a website, and then even Google will direct to
your secret page in a few weeks.
 
L

Lasse Reichstein Nielsen

Johannes Baagoe said:
Suppose the very worst case : you know absolutely nothing about the
plaintext, except that it is supposed to be read and understood by humans.

What simple property would still quite decisively set it apart from the
decryption with a wrong key ? How could you test that property by program ?

If it's text - then that's actually quite a hint. The plaintext will
then be in the same encoding (likely ASCII, UTF-8 or UC16), which is
easily detected as diffent from random bits.

That's why you should always zip before you encrypt.
On the other hand, if the receiver knows that you are zipping, he can
just unzip too.

/L
 
G

Garrett Smith

Mike said:
Garrett Smith :
[...]

Of course, you do not need javascript; just tell your friends to go to

http://what.ever.com/secret_xyz.html and don't tell anyone else.

A resource that is merely hidden does not have restricted access by
javascript or otherwise.

Jonannes Baagoe and Stockton are discussing encrypting strings and using
javascript to run decrpytion algorithms. That is a bit different. The
technique should be applicable also to anything with data uri, such as
images.

For purpose of the FAQ entry, I have shifted the focus on javascript
being used to restrict access to a web resource.

Discussions of cryptography are interesting but seem a bit too much for
the FAQ. If anyone feels otherwise, and feels that he is qualified to
draft an entry about that (I am not), then state so and do so.
 
R

Ry Nohryb

Ry Nohryb :


There is an easier way: decryption with a wrong key will always
return pseudo-random numbers, that is, with an approximately uniform
distribution. Whereas humanly readable text will always have quite
distinctive structure, often more or less according to Zipf's law,
and always characteristic of the relevant encoding, be it ASCII, UTF-8,
ISO 8859 or whatever. So even in the extraordinary case where we can't
guess the encoding, it is simply a matter of using a goodness-of-fit
test of the observed byte frequencies against the null hypothesis
that the distribution is uniform, which will be the case unless we
have found the key. Chi-square serves well and is quite fast.

How would you write that test ?

I've done one that checks that the percentage of "human chars" in a
given text is above a threshold %, and it seems to work quite well :

http://gist.github.com/400957

var humanityAcum= 0;
var humanityCount= 0;
var thisHumanity= 0;
var maxHumanity= 0;
var minHumanity= 1;

function isHumanTxt (txt) {
var humanChars= "abcdefghijklmnopqrstuvwxyz0123456789.,-><+-[]
¿?!'\"()= *";
var txt= txt.replace(/\r\n/g, "").toLowerCase();
var i= txt.length;
var ctr= 0;
while (i--) ctr+= (humanChars.indexOf(txt) >= 0);
humanityAcum+= (thisHumanity= ctr/txt.length);
if (thisHumanity > maxHumanity) maxHumanity= thisHumanity;
if (thisHumanity < minHumanity) minHumanity= thisHumanity;
humanityCount++;
return (thisHumanity) > 0.95;
}
(Of course, that won't work if the plain text has been compressed,
e.g., by LZW, *before* being encrypted - always a sensible thing to
do. But inspection of the code shows that it is not the case.)

Of course.
OK, that means it would take more than thousand years to try all
combinations - at present speed, which of course doesn't make sense.

But anyway - brute force is out, at least with ordinary means.

Except for short passwords.
And if AES is seriously flawed, it would be a major sensation, all the
very competent people who have given it their approval, both academics
and in the NSA and other agencies, would look very foolish indeed -
I don't think so.

I am slightly less happy with the mode of operation. CTR would not be
my choice, but I was too lazy to rewrite the function in CBC or OCB,
and anyway, it is probably good enough. I should check the details,
though, therein lies the devil.

By and large, I believe I have proved my point. Here is the key:

  Riekei1e (the next to last character is a one, not an el)

In my test that would have been the vector [4,49,35,48,35,49,54,35] ,
or the test # 4 + (49*62) + (35*62^2) + (48*62^3) + (35*62^4) +
(49*62^5) + (54*62^6) + (35*62^7) = 126.369.143.196.670 if starting
from [0,0,0,0,0,0,0,0] and going up. IOW, 667 years @ 6000 keys per
second. LOL.
The question is now: is it sufficiently interesting to justify the
rather boring task of turning into a proper application ?
A very small one, admittedly, but it still requires work.

No. The idea is clear enough. There's not much else to say or write or
prove about it, I think.
 
M

Mike Duffy

Mike Duffy wrote on 13 mei 2010 in comp.lang.javascript:


Because those "friends" are just like other people, they will
bookmark the result on a computer, that is accessable to someone
else, who will then use that url as a hyperlink on a website, and
then even Google will direct to your secret page in a few weeks.

Of course, you are correct. These friends are likely the same ones that
will include my email adress in their "bulk" emailings that they make
to all of their friends every time they find a funny joke or picture
while web-surfing.

Perhaps it would be better to use this kind of page-hiding only in
those cases when you have information that you *want* to disperse, but
make it appear to be restricted:

http://stock.tips.com/secret_picks_for_friends_only.html
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Thu, 13 May 2010 16:46:01, Garrett Smith
For purpose of the FAQ entry, I have shifted the focus on javascript
being used to restrict access to a web resource.

Such a subject, for the readership that you should be aiming for, will
merely add further disguise to whatever other meaning the item may be
intended to convey.

For a start, who is "I"? A question such as you propose could easily be
asked by a browser user wishing to keep his history secret, or wanting
to prevent his parents reading anything about Brussels sprouts.
 
G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
september.org>, Thu, 13 May 2010 16:46:01, Garrett Smith


Such a subject, for the readership that you should be aiming for, will
merely add further disguise to whatever other meaning the item may be
intended to convey.

For a start, who is "I"?

It is the hypothetical reader that appears in other entries, for
example: "how do I format a Date object with javascript," "my element is
named myselect[], how do I access it?

A question such as you propose could easily be
asked by a browser user wishing to keep his history secret, or wanting
to prevent his parents reading anything about Brussels sprouts.
How so?
 
V

VK

Jonannes Baagoe and Stockton are discussing encrypting strings and using
javascript to run decrpytion algorithms.

For what practical purpose? The page URL to navigate has to be in the
regular format, so easy to copy-paste from the address bar or from
right-click => properties.

Same for XHR call => document HTML replacement, just will take an
extra minute to see the algorithm.

This is the unsolvable default of any purely Javascript-based
protection: it may be very good, but only till the first authorization
of anyone with granted access. After that the URL can be copied and
shared with the whole world.
For purpose of the FAQ entry, I have shifted the focus on javascript
being used to restrict access to a web resource.

Discussions of cryptography are interesting but seem a bit too much for
the FAQ. If anyone feels otherwise, and feels that he is qualified to
draft an entry about that (I am not), then state so and do so.

I don't think that a "history of perpetuum mobile development
attempts" would be suitable for FAQ. Right now
http://www.jibbering.com/faq/#hideSource
it says everything what there are to say on the subject.
 
R

Ry Nohryb

Johannes Baagoe :

Ry Nohryb :
How would you write that test ?

In the specific case involved, `decrypt` returns a String, whose
charCodeAt method returns Numbers in [0, 65535] for any i between
0 and the length of the String minus 1. (In most other languages,
one would rather count bytes than unsigned 16-bit char codes.)

So we initialise an Array (let us call it `counts`) of 65536 zeros,
and loop over the decrypted String counting character codes :

  for (var i = plain.length - 1; i >= 0; i--) {
    counts[plain.charCodeAt(i)]++;
  }

(In real applications, this would be done incrementally, as the
decryption progresses. One may also stop before it is ended, once
a sufficiently large substring for the test has been decrypted.)

If the count distribution is close to uniform, each count will be
approximately equal to the length divided by 65536. Let us call that
value `expected`, and calculate Pearson's chi-square statistic :

  var expected = plain.length / 65536;
  var chi2 = 0;
  for (var i = 0; i < 65536; i++) {
    var diff = counts - expected;
    chi2 += diff * diff / expected;
  }

In the case of an unsuccessful decryption, the result will be
reasonably close to 65536. On successful decryption, it will be *much*
higher, say, above 70000 - the precise threshold that should ring
a bell depends on how much time you are prepared to spend in human
inspection of false positives vs. how much you want to be sure not to
miss the real solution. It also depends on the encoding, for ASCII,
you may be quite sure that all the counts above 127 will be 0, and
choose a corresponding very high test value - or a simpler test.
(A chi2 much *lower* that 65536, say, less than 60000, is either
a bug or a miracle.)

Scrupulous minds will note that Pearson's test may not be appropriate,
if for not nothing else, then because `expected` will be less than
5 for short plaintexts. In actual practice, it doesn't matter -
the test discriminates quite nicely, and it is faster than more
theoretically reputable ones.


If I understand it correctly, you look for an irregular, non-flat
distribution of frequencies. Well, it's ok, but as you know beforehand
which elements should exhibit a higher than average frequency, you
could as well, ISTM, look directly for that, as I did in my
isHumanTxt() code snippet, don't you think so ?
 
V

VK

And so what ?

So the end of it.
In case you missed the discussion, the page is here :http://baagoe.com/en/ES/encrypted.html

Inspect the code to your heart's content, and see if you can get in.
(That is, without looking up the password I published later.)

Oh, com'on, please... I am not going to the "chicken sh**" calls for a
longest time. If you really want to know where is the failure of your
approach, try comp.lang.java.security (having the algorithm ported to
Java of course). In the last century comp.lang.java.security was what
sci.lang was for the Fermat's Last Theorem. Just like anyone comes to
sci.lang for yet another "FLT simple proof", any new "encryption
genious" used to come to comp.lang.java.security with yet another
"bulletproof" encryption with both key and decoding in one block of
code. Some regulars used to have fun by posting the key, amount of
milliseconds spent and a short note where the poster went wrong. If
they are still there and not tired of that, you'll get an answer.
Quite, but sometimes, something that was dismissed as a perpetuum
mobile turns out to be more like Columbus's egg.

Sure. To not make myself looking as a retrograde person: I never
claiming on something "it is not possible because it is not possible".
Yet if someone comes with a perpetuum mobile schema of wheel A turning
wheel B which turning wheel A, I can state immediately that it doesn't
work - without studying all details of how "two wheels turning each
other" was obfuscated in this time.
Same for secure solutions of key and description algorithm being in
the same execution block. I don't know exactly where it is wrong, I
just know that it is wrong.
 
V

VK

VK :
yet another "bulletproof" encryption with both key and decoding in
one block of code.
[...]

Same for secure solutions of key and description algorithm being in
the same execution block. I don't know exactly where it is wrong,
I just know that it is wrong.

What makes you assume that the key is anywhere in the code ?

I trust you that you play fairly and that it's a purely client-side
Javascript solution, so using only static Javascript code and
(possibly) any amount of static client-side data files.
If it's so, then the rest is easy. Again: ask comp.lang.java.security,
they had zillions of key+decoder-noKeyExchange solutions, yours is not
the most obfuscated one from what I saw.
 
R

Ry Nohryb

Ry Nohryb :


Quite, the method I posted is for the general case where we don't know
what to look for, except that it is not random. Very often, one knows
a lot more than that, and a simpler test like yours may be sufficient.

You, on the other hand, go to the other extreme and assume it is
ASCII. Lots of human texts are not. Your test would fail on Russian
or Greek, mine would recognize Chinese and even cuneiform. (Not to
mention that some people who use non-English alphabets might object
to not being considered human.)

And rightly so!

For unknown payload types, the unix file command might be of help.
 
R

Ry Nohryb

I trust you that you play fairly and that it's a purely client-side
Javascript solution, so using only static Javascript code and
(possibly) any amount of static client-side data files.
If it's so, then the rest is easy. Again: ask comp.lang.java.security,
they had zillions of key+decoder-noKeyExchange solutions, yours is not
the most obfuscated one from what I saw.

VK, have you read this thread before posting ? All of it ? In any case
I think you should. (read or re-read it, whatever).
 
V

VK

I trust you that you play fairly and that it's a purely client-side
Javascript solution, so using only static Javascript code and
(possibly) any amount of static client-side data files.
If it's so, then the rest is easy. Again: ask comp.lang.java.security,
they had zillions of key+decoder-noKeyExchange solutions, yours is not
the most obfuscated one from what I saw.

As a side note: never use "application/ecmascript" for your scripts.
It is not recognized by IE of any version, so the whole script part
will be ignored, just like for scripting disabled - as it is right
now.
Use type="text/javascript" only or (obsolete but more logical)
language="JavaScript".

Also the form has to be brought into some more conventional way:
<form action="" onsubmit="return show(this.pass.value)">
<!-- with show() either making rewrite or returning false -->
Please enter the password: <input name="pass" type="password">
</form>

With these two defaults fixed - especially the first one - I'll ask my
worker at Monday what is wrong in this particular approach. I am
playing fairly - no password will be looked for anywhere in advance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,078
Messages
2,570,570
Members
47,204
Latest member
MalorieSte

Latest Threads

Top