简体   繁体   English

使用shell_exec()从PHP脚本调用C程序

[英]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. 我是Web开发的新手,目前,在构建“登录”页面时陷入困境。

I wrote a PHP script that gets the username and password when entered. 我写了一个PHP脚本,当输入时会获取用户名和密码。 The password is then sent as a parameter to a C program that I wrote, which just hashes the password(MD5). 然后将密码作为参数发送到我编写的C程序中,该程序只是对密码(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 现在,当我在登录表单中输入密码为1234时 ,得到的输出为f7d4cef3bfacebfc49d5574e7d9c1d6f

But when I use 1234 as my input while I am running the C program separately I get a different output 81dc9bdb52d04dc20036dbd8313ed055 . 但是当我分别运行C程序时使用1234作为输入时,会得到不同的输出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. 当我检查了各种在线MD5哈希程序后,它们给出了相同的输出。

In the C program, I use gets() to get the input and printf to display the output. 在C程序中,我使用gets()获取输入,并使用printf显示输出。 Also, I've used MySQL database(phpMyAdmin). 另外,我使用了MySQL数据库(phpMyAdmin)。

The C program CODE: C程序代码:

#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. 我已经读过许多内置函数,例如bcrypt,scrypt等。但这只是出于练习目的,因此想使用自己的代码。

Thank you 谢谢

Within your C program, assuming it is MD5 hashing the input string correctly, then it might actually be OK. 在您的C程序中,假设它是MD5,则正确地对输入字符串进行了哈希处理,那么实际上可能没问题。

The problem may not indeed be a problem at all, your MD5 hash can be correct from both processes. 这个问题可能根本不是问题,在这两个过程中,您的MD5哈希值都是正确的。 (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. (即使它们看起来完全不同,它们也可以' 保持 '相同的值'1234' )只是堆栈的内容在一个实例与另一个实例之间是不同的,并且null之后的某些字符串来自堆栈。

What is happening is that in one instance the C function is hashing this string '1234__________________' (where _ is the null or \\0 char 发生的情况是,在一个实例中,C函数正在对该字符串'1234__________________'哈希'1234__________________' (其中_是null或\\ 0 char

and the other instance is hashing this string '1234_some_random_values' . 而另一个实例正在对该字符串'1234_some_random_values'哈希'1234_some_random_values'

Both strings contain 1234 following by the null character, but the characters AFTER the null are different. 两个字符串都包含1234一个null字符,但是在空后的字符是不同的。

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. 尝试用所有空值预填充您的临时字符串,然后在密码之间进行复制,以确保在MD5对其进行哈希处理之前,确保字符串缓冲区的其余部分为“空”。

(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: (如果您想验证我是正确的,则可以通过unMD5散列来确认。在Wikipedia上,您可以看到散列算法接受数据的“块”,而不关心NULL字符在哪里:

MD5 processes a variable-length message into a fixed-length output of 128 bits. MD5将可变长度消息处理为128位固定长度输出。 The input message is broken up into chunks of 512-bit blocks (sixteen 32-bit words); 输入消息分为512位块(十六个32位字)的块; the message is padded so that its length is divisible by 512. 填充该消息,以便其长度可被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. 从这里https://en.wikipedia.org/wiki/MD5也是从这个解释开始,如果您的密码长度恰好是16个32位字(16个32位字)乘以16 = 64个字符,那么MD5哈希应该相同空字符后面的字符数组中的内容,因为该算法将不会在64个字符的边界之后查找更多字符。 )

Try adding 尝试添加

memset(msg,0,500); 

before your gets . 在你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 熟悉PHP标准库,特别是

    http://php.net/manual/en/function.md5.php http://php.net/manual/zh/function.md5.php
    http://php.net/manual/en/function.filter-input.php http://php.net/manual/zh/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. 我首先列出了安全性,因为,正如其他人指出的那样,您不应该直接访问GET或POST。 Since you're just practicing, start programming with security always in your mind, don't reinvent the wheel and good luck to you. 由于您只是在练习,因此在编程时始终要牢记安全性,不要重蹈覆辙,祝您好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 c ++程序无法通过php脚本(例如exec(),shell_exec(),system()等命令)执行 - c++ program not getting executed using php script with commands like exec(),shell_exec(),system() 使用 shell_exec 从 php 调用 perl 脚本 - using shell_exec to call a perl script from php PHP:shell_exec是一个shell脚本,而shell_exec是一个Linux上的程序(权限) - PHP: shell_exec a shell script vs. shell_exec a program on linux (permissions) 使用shell_exec()或system()或exec()函数无法从php脚本运行命令 - command is not running from php script using shell_exec() or system() or exec() functions Fail2ban - 使用 exec 或 shell_exec 从 php 脚本手动添加 ip - Fail2ban - Add manually ip from php script using exec or shell_exec 为什么我不能使用exec,shell_exec,system从PHP运行作曲家脚本? - Why can't I run the composer script from PHP using exec, shell_exec, system? 调用shell_exec显示来自php的奇怪行为 - Calling shell_exec shows weird behavior from php 如何使用PHP shell_exec运行外部php脚本? - How to run external php script using Php shell_exec? 无法使用 PHP shell_exec() 向 Java 程序提供输入 - Can not give input to a java program using PHP shell_exec() 在 php 中使用 shell_exec 调用 gcc - Calling gcc with shell_exec in php
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM