実験四linuxの下のc言語のプログラミングとgccツールの使用

5232 ワード

実験4
一、実験目的
Linuxの下のユーザー管理メカニズムを理解して、Linuxの下のC言語のプログラミングとgccツールの使用を熟練して掌握します.
必要な知識:C/C++言語の基本技能、第9章ユーザー管理知識、第12章gccの使用.
 
二、実験内容
Linuxシステム管理の重要な仕事はユーザー管理です.ユーザのパスワードは、パスワードファイル/etc/shadowに暗号化された形式で格納されます.弱いパスワードは、ユーザー名と同じパスワード、「123456、admin、computer」のような一般的なパスワードなど、推測されやすいパスワードです.パスワード辞書は、いくつかの一般的な弱いパスワードをテキストファイルに書くことを指します.管理者は、システムに弱いパスワードがあるかどうかを定期的に検出する必要があります.c言語プログラムを作成して、自分のLinuxシステムに弱いパスワードがあるかどうかをアクティブにチェックしてみましょう.
 
三、実験手順
手順1:/etc/shadowファイルのフォーマットを分析します.
独自のシステム内のファイルのフォーマットを表示できます.9.1節の説明を参照してください.このファイルの各行はユーザーに対応しています.次はシステム内の/etc/shadowファイルの例です.
user1:$6$DVLiBPZG$IrR9o0KpjtGQOj7I5WvgxQ.jMQ/Qzl3cJp4w0loUMZs4xQSQ8wkdIK7Sdkdk2pMXeAfOYq9O07r/QuDdJ8f3c0:14748:0:99999:7:::
user2:$6$RR8pmW2aerqIkySA$PcMV7/Z37QFCe9hJrf1rlUjPTAOdmKsW/mfG40V343kxG1QNsWWI7mdzl.50SCJpI4TQ/x4z4zsCoiA48EjAn1:14748:0:99999:7:::
user3:$6$oGG.739y$9ysybZ.VaTQ7dmR1zyz1vR8OiCUSCnzqnFd1PUYvedJMt.t6ElISwUohtOAlqAuT7.sPDjfy.bKCKar82mSp2.:14748:0:99999:7:::
user4:$6$AJerec5o$bwgJnQ0mTPzZMRCZYuivQVsWtD9mlh3.pWK2tR2pZPr4NzSlqk6hhFq3/zfWJXQCNmXJTlZhubwwW9x6a8mtM0:14748:0:99999:7:::
user5:$6$o1DA6WOiXtme7Zsw$Lj6bXgI5c5Kg/GewGWYv.4pQ0fD/AnSYEjMvmXxuvzEK3IYhNYjnTIEnTPQr9pZIMzatBOyrC4FgBjYtR5R.n1:14749:0:99999:7:::
user6:$6$UUXC4WKX$mKyl/32n7xrU1ChPIJYs2gwYuEoObdkNsPcVhxR22xFBIspNjVIfRv4FgoDWsJIxy4TZ.ci70MeDvDMEeExXL0:14749:0:99999:7:::
手順2:Linuxのパスワード暗号化の原理を理解する
パスワードの暗号化はLinuxシステムのcrypt関数を使用します.infoまたはmanを使用して、このコマンドの動作原理を理解することができる:Red Hat Linux 9で使用されるMD 5アルゴリズム、Fedora 10ではSHA-512アルゴリズムがデフォルトで使用されている.文字列をsalt(塩に翻訳)として使用し、長さは8~16バイトで、ユーザーが入力したパスワードkeyを暗号化します.関数crypt(key,salt)の結果は/etc/shadowファイルの2番目のドメインに格納されます.このドメインの前の$6$salt$はcrypt関数のsaltパラメータです.ユーザにパスワードを設定するとsaltはシステムによってランダムに選択されるため、同じkeyでもsaltによって2番目のドメインの値が異なる.
ユーザがログイン中に自分のパスワードを入力すると、cryptを使用して同様の計算を行い、得られた結果が/etc/shadowに格納されているものと一致すると、ユーザのログインを受け入れる.
手順3:弱いパスワードとは何ですか:弱いパスワードは、admin、guest、flower、123456、beautyなど、推測されやすいパスワードです.パスワードの推測や解読では、通常、すべての文字のすべての配列の組み合わせを尽くすことはありません.一般的には、パスワードとしてよく使われる文字列を含む弱いパスワード辞書が使用されます.インターネットでパスワード辞書を探すことができます.
手順4:弱いパスワードチェックの原理
各ユーザにとって、パスワードとしてよく用いられる語を1つずつcryptを用いて演算し、演算結果が/etc/shadowに格納された暗号化されたパスワードと同じであれば、パスワードが推測される.
ステップ5:c言語でパスワードチェックを実現するプログラムを作成する
キーのコードは次のとおりです.
/etc/shadowの各行を読み出すことで、pwdに格納されるユーザに関するデータ構造が得られる.
char saltstr[21];//シードを保存、最大20バイト
    bzero(saltstr,sizeof(saltstr));//すべてをクリアする
strncpy(saltstr,pwd->pw_passwd,20);
//saltを最大20バイト取り出し、そのうち$を境界とする
    cp = crypt (guess, saltstr);//crypt暗号化関数の呼び出し
if(strcmp(cp,pwd->pw_passwd)/パスワードファイルに格納されている情報と比較
          return (0);//一致しなければ戻る
printf ("Warning! Password Problem: Guessed:\t%s\tpasswd: %s",
pwd -> pw_name, guess);//パスワードを見つけて、パスワードを表示する
手順6:コンパイラ
gcc –o passchk pass.c –lcrypt
ここで、-oオプションはコンパイル後の実行可能ファイル名を指定し、-lオプションはcrypt関数ライブラリを使用することを示します.
手順7:パスワードチェックプログラムの実行
./passchk –P myshadow –w words –p
ここでpasschkは実行可能ファイル名、mysadowはパスワードファイル、Pオプションがない場合はデフォルトでLinuxシステムの/etc/shadowファイル、wordsは弱いパスワードを格納するパスワード辞書ファイル、オプション-pは解読後のパスワード出力を表す. 
 
四、実験結果
1、/etc/shadowをmysadowにコピーする
 
2、パスワード辞書wordsの編集
 
3、コンパイラ
 
4、プログラムの実行
#include 
#include 
#include 

int main(int args, char* argv[]){
    char* dir1;
    char* dir2;
    int flag = 0;
    for(int i = 0; i < args; i++){
        if(argv[i][0] == '-'){
            if(argv[i][1] == 'P'){
                dir1 = argv[i + 1];
                flag = 1;
            }
            if(argv[i][1] == 'w'){
                dir2 = argv[i + 1];
            }
        }
    }
    FILE* myshadow;
    if(flag) myshadow = fopen(dir1, "r");
    else myshadow = fopen("/etc/shadow", "r");
    char buf1[500];
	char buf2[500];
    int index[5];

	while(!feof(myshadow)){
        fgets(buf1, 500, myshadow);
        if(feof(myshadow)) break;
        int count = 0, flag = 1;
        for(int i = 0; i < strlen(buf1) && count < 5; i++){
            if(buf1[i] == ':' || buf1[i] == '$'){
                index[count++] = i;
                if(buf1[i] == '$') flag = 0;
            }
        }
        if(flag) continue;
        FILE* words = fopen(dir2, "r");
        while(!feof(words)){
            fgets(buf2, 500, words);
            if(buf2[strlen(buf2) - 1] == '
') buf2[strlen(buf2) - 1] = '\0'; char salt[50]; char psw[500]; char name[50]; bzero(salt, sizeof(salt)); bzero(psw, sizeof(psw)); bzero(name, sizeof(name)); strncpy(salt, buf1 + index[0] + 1, index[3] - index[1] + 1); strncpy(psw, buf1 + index[0] + 1, index[4] - index[1]); strncpy(name, buf1, index[0]); char* cp = crypt(buf2, salt); if(strcmp(cp, psw) == 0){ printf("Warning! Password Problem: Guessed:\t%s\tpasswd: %s
", name, buf2); break; } } fclose(words); } fclose(myshadow); return 0; } // , AC