0

ユーザーが呼び出すのではなく、ルートとしてbashスクリプト(shスクリプトではなくbashを読む)を起動したかったのですが、bashはスクリプトのsetuidを無視するため、スクリプト/引数を取り、それを呼び出す非常に小さなスクリプトを作成することにしましたsetuid セットで。

これはうまく機能し、プログラムの誤用を避けるために、スクリプトにsetuidが設定され、実行可能であり、rootとしてではなくファイルの所有者でsetuid()が呼び出されていることをさらに確認し、以下のプログラムになりました..

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
  char *command;
  int i, file_owner, size = 0;
  struct stat status_buf;
  ushort file_mode;

  // Check argc
  if (argc < 2) {
    printf("Usage: %s <script> [arguments]\n", argv[0]);
    return 1;
  }

  // Make sure the script does exist
  if(fopen(argv[1], "r") == NULL) {
    printf("The file %s does not exist.\n", argv[1]);
    return 1;
  }

  // Get the attributes of the file
  stat(argv[1], &status_buf);

  // Get the permissions of the file
  file_mode = status_buf.st_mode;

  // Make sure it's executable and it's setuid
  if(file_mode >> 6 != 567) {
    printf("The file %s should be executable and should have setuid set, please chmod it 0106755.\n", argv[1]);
    return 1;
  }

  // Get the owner of the script
  file_owner = status_buf.st_uid;

  // setuid
  setuid(file_owner);

  // Generate the command
  for (i = 1; i < argc; i++) {
    size += strlen(argv[i]);
  }
  command = (char *) malloc( (size + argc + 11) * sizeof(char) );
  sprintf(command, "/bin/bash %s", argv[1]);
  if (argc > 2) {
    for (i = 2; i < argc; i++) {
      sprintf(command, "%s %s", command, argv[i]);
    }
  }

  // Execute the command
  system(command);

  // free memory
  free(command);

  return 0;
}

この演習は私の問題を解決するためだけでなく、C をさらに理解するための方法でもありました。改善すべき点はありますか?

ありがとうございました..

4

1 に答える 1

2
if(file_mode >> 6 != 567) {

マジックナンバーはダメです。S_I*代わりにビットマスクを使用してください。

system(command);

あなたは* nixにいます。と を使用するとfork()exec*()直前のループで実行されたほとんどのアクロバットがなくなります。

于 2011-06-09T09:29:47.483 に答える