简体   繁体   中英

Calling C program from a PHP script using shell_exec()

I am totally new to Web Development and currently, I am stuck while building a Login page.

I wrote a PHP script that gets the username and password when entered. The password is then sent as a parameter to a C program that I wrote, which just hashes the password(MD5). This is done using the following code:

$username = $_POST['uname'];
$password = $_POST['passwd'];

$hashvalue = shell_exec("md5.exe $password");

Now when I enter my password in the login form as 1234 I get an output of f7d4cef3bfacebfc49d5574e7d9c1d6f

But when I use 1234 as my input while I am running the C program separately I get a different output 81dc9bdb52d04dc20036dbd8313ed055 . This is also the output that I should actually be getting. As I checked with various online MD5 hashing programs which gave the same output.

In the C program, I use gets() to get the input and printf to display the output. Also, I've used MySQL database(phpMyAdmin).

The C program CODE:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

typedef union uwb {
    unsigned w;
    unsigned char b[4];
} MD5union;

typedef unsigned DigestArray[4];

unsigned func0( unsigned abcd[] ){
    return ( abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]);}

unsigned func1( unsigned abcd[] ){
    return ( abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]);}

unsigned func2( unsigned abcd[] ){
    return  abcd[1] ^ abcd[2] ^ abcd[3];}

unsigned func3( unsigned abcd[] ){
    return abcd[2] ^ (abcd[1] |~ abcd[3]);}

typedef unsigned (*DgstFctn)(unsigned a[]);



unsigned *calctable( unsigned *k)
{
    double s, pwr;
    int i;

    pwr = pow( 2, 32);
    for (i=0; i<64; i++) {
        s = fabs(sin(1+i));
        k[i] = (unsigned)( s * pwr );
    }
    return k;
}


unsigned rol( unsigned r, short N )
{
    unsigned  mask1 = (1<<N) -1;
    return ((r>>(32-N)) & mask1) | ((r<<N) & ~mask1);
}

unsigned *md5( const char *msg, int mlen)
{
    /*Initialize Digest Array as A , B, C, D */
    static DigestArray h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
    static DgstFctn ff[] = { &func0, &func1, &func2, &func3 };
    static short M[] = { 1, 5, 3, 7 };
    static short O[] = { 0, 1, 5, 0 };
    static short rot0[] = { 7,12,17,22};
    static short rot1[] = { 5, 9,14,20};
    static short rot2[] = { 4,11,16,23};
    static short rot3[] = { 6,10,15,21};
    static short *rots[] = {rot0, rot1, rot2, rot3 };
    static unsigned kspace[64];
    static unsigned *k;

    static DigestArray h;
    DigestArray abcd;
    DgstFctn fctn;
    short m, o, g;
    unsigned f;
    short *rotn;
    union {
        unsigned w[16];
        char     b[64];
    }mm;
    int os = 0;
    int grp, grps, q, p;
    unsigned char *msg2;

    if (k==NULL) k= calctable(kspace);

    for (q=0; q<4; q++) h[q] = h0[q];   // initialize

    {
        grps  = 1 + (mlen+8)/64;
        msg2 = malloc( 64*grps);
        memcpy( msg2, msg, mlen);
        msg2[mlen] = (unsigned char)0x80;
        q = mlen + 1;
        while (q < 64*grps){ msg2[q] = 0; q++ ; }
        {
            MD5union u;
            u.w = 8*mlen;
            q -= 8;
            memcpy(msg2+q, &u.w, 4 );
        }
    }

    for (grp=0; grp<grps; grp++)
    {
        memcpy( mm.b, msg2+os, 64);
        for(q=0;q<4;q++) abcd[q] = h[q];
        for (p = 0; p<4; p++) {
            fctn = ff[p];
            rotn = rots[p];
            m = M[p]; o= O[p];
            for (q=0; q<16; q++) {
                g = (m*q + o) % 16;
                f = abcd[1] + rol( abcd[0]+ fctn(abcd) + k[q+16*p] + mm.w[g], rotn[q%4]);

                abcd[0] = abcd[3];
                abcd[3] = abcd[2];
                abcd[2] = abcd[1];
                abcd[1] = f;
            }
        }
        for (p=0; p<4; p++)
            h[p] += abcd[p];
        os += 64;
    }
    return h;
}

int main( int argc, char *argv[] )
{
    int j,k;
    char msg[500];
    gets(msg);
    unsigned *d = md5(msg, strlen(msg));
    MD5union u;
    for (j=0;j<4; j++){
        u.w = d[j];
        for (k=0;k<4;k++) 
            printf("%02x",u.b[k]);
    }
    return 0;
}

What am I doing wrong?

I've read about many inbuilt functions like bcrypt, scrypt etc. But this is just for practice purpose and hence wanted to use my own code.

Thank you

Within your C program, assuming it is MD5 hashing the input string correctly, then it might actually be OK.

The problem may not indeed be a problem at all, your MD5 hash can be correct from both processes. (Even though they look entirely different, they can ' hold ' the same value '1234' ) It is just that the stack has different content from one instance to another, and some of your string AFTER the null comes from the stack.

What is happening is that in one instance the C function is hashing this string '1234__________________' (where _ is the null or \\0 char

and the other instance is hashing this string '1234_some_random_values' .

Both strings contain 1234 following by the null character, but the characters AFTER the null are different.

Trying pre-filling your temporary string with all null values, then copy across your password, so that you are sure that the rest of the string buffer is 'empty' before you MD5 hash it.

(You can confirm this by unMD5 hashing if you like to verify I am correct. From Wikipedia, you can see the hash algortihm takes 'blocks' of data and does not care where the NULL character is:

MD5 processes a variable-length message into a fixed-length output of 128 bits. The input message is broken up into chunks of 512-bit blocks (sixteen 32-bit words); the message is padded so that its length is divisible by 512.

from here https://en.wikipedia.org/wiki/MD5 Also from this explanation if your password length was exactly (sixteen 32-bit words) 4 times 16 = 64 characters long, then the MD5 hash should be the same regardless of what follows in the character array after the null character, as the algorithm will not look for more characters after the 64 char boundary. )

Try adding

memset(msg,0,500); 

before your gets .

(I am disregarding all the security concerns :) )

I think this might be a great point for you to do 2 things

  1. start thinking about the security of your design
  2. familiarize yourself with PHP standard lib, specifically

    http://php.net/manual/en/function.md5.php
    http://php.net/manual/en/function.filter-input.php

I listed security first because, well, as some others have pointed out, you shouldn't be accessing the GET or POST directly. Since you're just practicing, start programming with security always in your mind, don't reinvent the wheel and good luck to you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM