just wanted to add that your custom security level suggestions are well thought 
out.

http://www.jsoftware.com/jwiki/System/Interpreter/Requests07#custom_security_levels



----- Original Message -----
From: Dan Bron <[email protected]>
To: J Programming <[email protected]>
Cc: 
Sent: Tuesday, August 11, 2015 11:23 AM
Subject: Re: [Jprogramming] unlock.ijs

> Btw, the only secret I want to keep safe is the noun 'password' by embedding 
> it in a locked verb 


If you’re really concerned about the security of this password, it should not 
appear in memory in cleartext at all.  You should only deal in hashes and 
comparing hashes.

> that is set at run time, 


Having a user define a verb at runtime is a bit unusual. More typical would be 
to have them supply the password in a text field, and then creating the verb 
from that (which you could do automatically, obviously). 

> pwdcheck =: localvar&('password' [:`(dostuff@[)@.-: ])


Again, where the 8 letters p a s s w o r d coming from? Is someone typing in 
the full sentence pwdcheck =: localvar&(‘password’ …)  into the session 
manager, manually, every time J is started? (I ask because if that’s *not* the 
case then you’ve got more points in the workflow where the password could be 
intercepted, even before the name is locked by 3!:6.)

> Does 9!:25 disable the 15!:n commands?

Nope. And security level (9!:25) is extremely out of date; I wouldn’t rely on 
it in general [1].

> Though I don't see a single bit difference in an int there.

Yes, that’s what I meant by “requires more pointer chasing” yesterday. I don’t 
have a complete understanding of the J engine’s memory layout yet, but these 
structures in turn point to other structures, and somewhere down the chain, 
there’s a struct A with a flags field (second word) having the VLOCK bit set. 
It would/will take more investigation to understand how to get from the 
structures we have in hand to the ultimate structure containing the value of 
pwdcheck. It’s a SMOP ;)

Incidentally, the only differences in the memory dumps you quoted:

> 56 0 184 262144 2 1 0 6443034000 6443033120 626935840960
> 
> 56 0 184 262144 1 1 0 6443034000 6443033120 625002615568

Are in the 5th and final integers. The 5th integer is a reference count. If you 
delete one of the names pointing to pwdcheck (e.g. erase’pwdcheck’) and call 
memr again, you’ll see that 2 change to a 1 (or, vice versa, point another name 
to the 2nd memory structure, and you’ll see its reference count go up).

Note that the initial 56 in the original data dumps indicate the “ravel”, 
“value”, or “data” section of the struct starts after 56 bytes, or seven 8-byte 
integers (on my 64-bit machine). Therefore everything from 6443034000 
6443033120 .. onwards is considered the “value” of this array. I haven’t yet 
worked out what these initial two values mean, but the third value, the one 
that differs in the two arrays above, I believe is a pointer to the name (or 
one of the names?) for the verb. If you do 

        SZI =: IF64 { 4 8
        a =: memr (15!:14 <'PWDCHECK'), 0, 1, JINT

        memr a,(SZI*9),1,JINT
     140205391245200

        namen =: memr a,(SZI*9),1,JINT
        memr namen,0,16,JINT
     64 0 48 33554432 2 8 1 8 10699157 0 0 7307199678560337928 27491 0 0 7

You’ll see the 4th integer here, type, is 33554432 (2^25), which means “name” 
[2]. The 8 1 8 bit changes depending on which name you’re inspecting. I 
originally though the 8 corresponded to the 8 characters in ‘pwdcheck’, but on 
further investigation that turned out to be a red herring (then I thought maybe 
the 8 was an index into the global symbol table, but 8 seems suspiciously low 
for a name created so late in the J session).

The subsequent six values in the original arrays,

> 0 0 0 9223372036854775807 9223372036854775807 9223372036854775807 


have been the same in all verbs I’ve inspected so far, and look like sentinels 
to me (3 3 # 0, 2^64-1): three pairs of mins and maxes?

Finally, if you read a little further into memory, you’ll find several more 
pointers until you hit the next entry in table (i.e. the next series of bytes 
which follow the same pattern as the two arrays quoted above). It may be in 
these pointers that the value of the verb pwdcheck is hidden.

All we know is it’s there somewhere, and therefore with enough effort we can 
expose it.

> I guess even if it did, external processes can read memory.

Yes, this is what I meant with my advice that 3!:6 is merely an encoding, not 
true encryption. I promise you the string ‘password’ appears *somewhere* in the 
J process’ memory (else -: couldn’t match against it). 

The advantage we have from doing this inside of J is we have a handle on where 
to start (i.e. with 15!:6), but in theory a process with access to J’s memory 
(if not protected by the OS and/or hardware exceptions) could just scan the 
whole thing looking, seriatim, for likely strings. Even if 15!:6 were taken 
away from us in J completely, we could simulate this memory-scanning starting 
from square one with 15!:0 (call external library, likely OS APIs).

All I want to drive home is that this security model is breakable. Certainly 
using 3!:6 makes it *harder* to access your sensitive data, and that’s a good 
thing, but it should not lull you into a false sense of perfect, or even 
particularly high, security.  

-Dan


[1] security level out of date
    
http://www.jsoftware.com/jwiki/System/Interpreter/Bugs#security_level_out_of_date
 
<http://www.jsoftware.com/jwiki/System/Interpreter/Bugs#security_level_out_of_date>

[2] Interpretations of struct A’s “type” field:
    
https://github.com/openj/core/blob/18fd23bbdc2f50770eb3047e978cd5e4e3b47039/jtype.h#L123
 
<https://github.com/openj/core/blob/18fd23bbdc2f50770eb3047e978cd5e4e3b47039/jtype.h#L123>



----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to