Julgon has asked for the wisdom of the Perl Monks concerning the following question:


Hi everyone, ok after spending 3 whole days trying to figure it out.
I'm recurring to all of you, cause i'm almost convince there is not possible solution.


*** Let me explain my Working Context and the Problem:

This is my Context (dont ask why, just asumme it) :

1) i must used perl and only perl for this scripting developing.
2) At some point i use the DBI for Oracle connection (also SQLSERVER)
3) While this "custom scripting" is in a somewhat "closed environment", I have to let the script for public access (so anyone could see the code) BUT I cannot have the db user and password hanging around in the code.


The Problem, is then that:
Currently, i "masked" the db credentials with a crypting perl library, but cause there is all in source code, there is no way of really deny access in the credentials:
A snip of my scripts so all of you can understand:

my $dbInstance = "XE";
my $db_user = `perl -S decrypter.pl \"$dbusercryptedfile\"`;
my $db_pass = `perl -S decrypter.pl \"$dbpasswordcryptedfile\"`;
my $q_string = "dbi:Oracle:$dbInstance";
my( $dbh,$sth);
$dbh = DBI->connect ( $q_string, $db_user, $db_pass,{PrintError => 0, RaiseError => 1} );
...
...
...

As you can see, anyone can see the password doing a simple print "$db_pass"


*** The solution i "thought" was possible:

The only thing a maybe think was feasible, was making a dbconnection.pl and then perl2exed.
The code snippet of this dbconnection.pl is

my $db_user = decrypter($dbusercryptedfile);
my $db_pass = decrypter($dbpasswordcryptedfile);
my $q_string = "dbi:Oracle:$dbInstance";
my( $dbh,$sth);
$dbh = DBI->connect ( $q_string, $db_user, $db_pass,{PrintError => 0, RaiseError => 1} );
print \$dbh;
exit 0;


So then in my main scripts i could do something like:

$dbconn = `dbconnection.exe`;
print "|$dbconn|\n";
$stmt = $dbconn->prepare($strSql);
$stmt->bind_columns( undef, \$qFieldContent);
$stmt->execute();


The thing is the $dbconn never get the correct reference.
I try and play with the references methods, but didn't find a solution.
The two times i get "closed" with $dbconn were:
dbconn|REF(0x1aa3760)|
dbconn|DBI::db=HASH(0x1b09c1c)|

the problem is that both values are string values, and not actually a class or a ref value.
Maybe is there a way to actually reference an address that a string represent ???


***********


There it is. My problem and flimsy (/not working) solution.

If anyone have an alternative for what I need, or the solution for this reference workaround, you'll really help me

Thanks anyway guys

  • Comment on From string with variable Address to actual referencing that address? (core crypting problem)

Replies are listed 'Best First'.
Re: From string with variable Address to actual referencing that address? (core crypting problem)
by ikegami (Patriarch) on Apr 19, 2011 at 15:53 UTC

    Each process has its own memory space. A pointer cannot be passed between processes. Think about it this way: If a process could see $dbh, it could also see $db_pass.

    I dou't see the point of this exercise. If you give them access to the database, what does it matter whether they know the password or not?

      Its all because of the security and roles delegation the company has...

      The SCM admin could see the scripts (and make new version with new features), but they want him to not have access to the actual credentials of the database (thats for the dba)

      Sadly company rules... not mine

      Any alternative for what i need?

        but they want him to not have access to the actual credentials of the database (thats for the dba)

        Giving them the dbh is also giving them the credentials. Credentials don't just come in the form of passwords, and passwords aren't necessarily credentials on their own (say if you only accept connections from certain IP addresses).

Re: From string with variable Address to actual referencing that address? (core crypting problem)
by BrowserUk (Patriarch) on Apr 19, 2011 at 21:50 UTC

    Update:Added emphasis to highlight that the source is unavailable.

    Whilst I agree it is the procedures that need fixing, I have also had the unhappy experience of working at a place where 'rules is rules', no matter how silly.

    The best option I can come up with is to create a DLL/SO using XS that can be accessible in binary form only, that has an entrypoint that makes the connection to the DB and returns the DBI handle. The DLL/SO contains the user/pass encrypted. When called, the entrypoint decryptes the user/pass, evals code that loads the appropriate modules and calls the connect and returns the dbh.

    Here simulated using Inline::C and crap encryption, just for a flavour of the sort of thing I mean. (Note: I do not have a user called root with a password secret, hence the error):

    #! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'secret', CLEAN_AFTER_BUILD => 0; static char code[] = "\ use DBI;\ use DBD::Pg;\ DBI->connect(\"dbi:Pg:database=test;\", 'EXXC', 'DRTERC' )\ "; static char *user = code + 59; static char *pass = code + 67; SV *getDBH ( SV *dummy ) { int i; for( i = 0; i < 4; ++i ) user[ i ] ^= 55; for( i = 0; i < 6; ++i ) pass[ i ] ^= 55; // The next line is (obviously) for demonstration purposes only!!! printf( "'%s'", code ); return eval_pv( code, 1 ); } END_C print getDBH( 'fred' ); __END__ C:\test>secret 'use DBI;use DBD::Pg;DBI->connect("dbi:Pg:database=test;", 'root', 'se +cret' )' DBI connect('database=test;','root',...) failed: could not connect to server: Connection refused (0x0000274D/10061 +) Is the server running on host "???" and accepting TCP/IP connections on port 5432? at (eval 10) line 1 Use of uninitialized value in print at C:\test\secret.pl line 29. Attempt to free unreferenced scalar: SV 0x411b660, Perl interpreter: 0 +x29fb8.

    Written in XS with only the resultant dll accessible to the user (execute only if that possible on your system). And using a better encryption, probably on the whole connection string rather than just the user/pass, this would defeat most casual attempts at discovery.

    You might also require that the user pass in some arbitrary (but checked) token into the api--say '811f8915e99fbed4b814174de746d0485bf63f8705a5b7bfc0b178c525798a49' or similar that you give the programmer(s). That might divert attention from the real location of the relevant information for a while. Provided that they are not also PM users :)

    Or you might use the token passed as a part of the decryption process, thereby allowing you to embed the credentials of several accounts and have the token also select which set of credentials are used for the connection.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      THANKS BrowserUk!!!

      that exactly what i was looking for. To be honest i didnt know of the existence of the XS and the posibilites of perl handle dll, with this i'll make the binaries dlls with the connection access as you suggest.

      While its still can be "hacked", i'm more than sure this would be accepted as a "safe" procedure.

      I just want to thank everyone for the professional advices and help, was greatly appreciate it.

      Regards
        my $old = \&DBI::connect; sub DBI::connect { print("@_\n"); goto &$old; }

      You can still do what's he's asking to avoid.

      printf("%s %s\n", user, pass);

      The only thing you did is switch the language.

        How so? I thought he was opening the database handle within the XS code and then passing the handle back to the script.

        Elda Taluta; Sarks Sark; Ark Arks

        Do you ever bother to actually read the posts you reply to?

        Or did you choose to ignore "accessible in binary form only", just so that you could find something to say in pursuit of your XP whoring?

Re: From string with variable Address to actual referencing that address? (core crypting problem)
by locked_user sundialsvc4 (Abbot) on Apr 20, 2011 at 14:06 UTC

    The best way to authenticate a web-server is through a third party agent such as OpenDirectory (LDAP).   Procedures for doing this vary from server to server, and company to company.

    If the app must present some kind of identifying token, it should be a token that only has meaning when presented by this server at this IP.   (For example, when the connection wants to align itself to what it has been GRANTed to do, if different levels of database privilege are obtainable at different times.)  It must be utterly worthless if stolen.   The third party (LDAP) vouches for both servers, one to the other.

    I do not mean to be condescending if I go on to state that, in an “intranet” setting, LDAP should be used to authenticate and to authorize the connecting web-users also.   The web server can restrict access to an entire site (or any portion thereof) based on the LDAP settings of the connecting user, and can reliably use group-membership etc. in its own code, without bothering with any sort of separate password-system of its own devising.   The same (trustworthy) credentials can be presented to the database servers and so on.   If the connecting user is coming in “from the Internet,” then the user’s identity cannot be strongly trusted, but the database server can nonetheless trust the web-server to some degree, although not to the degree that it could trust a (separate...) web-server that it knows can only be reached from “inside.”   In any case, the use of “passwords” is not appropriate, unless those passwords are configured such that they are useless if presented by any party other than the designated web servers ... a determination that should be made, once again, by a centrally-managed authentication authority, i.e. LDAP.   (And if all of this preceding ¶ is “old news to you,” ... well, of course it is ... of course.)