유저레벨 프로세스가 루트권한을 획득할려면...

dolsemix의 이미지

제가 원하는 기능은 다음과 같습니다.
1. 일반 유저로 로그인
2. 유저레벨의 프로세스를 실행
3. 프로세스에서 루트 패스워드를 입력받음
4. 프로세스 자체에서 루트 인증하여 하드웨어 제어 기능 수행

한컴리눅스의 삼바서버 설정프로그램이 이런기능을 지원했던것 같은데 어떻게 구현하는지를 모르겠습니다.
나름대로 getuid/setuid 함수류를 이용하여 시도해 보았지만 접근방법이 틀린것 같네요...
프로세스에게 루트세션을 할당해줘야 할것 같은데...
아시는분 있으시면 한수 지도 바랍니다...

liongo의 이미지

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


int main() 
{ 
        setuid(0); 
        system("id"); 
        return 0; 
}                                        

compile: 
        >> gcc filename.c -o filename 

suid set 
        >> chmod 4755 filename 

Quote:
[user@systems user]$ id
uid=514(user) gid=514(user) groups=514(user)
[user@systems user]$ ls -al suid
-rwsr-xr-x 1 root root 11691 May 14 10:55 suid
[user@systems user]$ ./suid
uid=0(root) gid=514(user) groups=514(user)
[user@systems user]$ id
uid=514(user) gid=514(user) groups=514(user)

혹시 이런걸 말씀하시는건지 질문의 의도를 정확하게 모르겠습니다..

관계없는 글이었다면 죄송..

' 형식이 내용을 규정한다. '

liongo의 이미지

이건 정말 심심해서 만들어본겁니다 ㅡㅡa

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
        int _uid = 0;

        _uid = getuid();
        system("id");
        system("ps -aux | grep a.out");
        sleep(5);

        setuid(0);
        system("id");
        system("ps -aux | grep a.out");

        sleep(5);
        setuid(_uid);
        system("id");
        system("ps -aux | grep a.out");

        sleep(5);
        return 0;
}                         

Quote:
[user@systems user]$ ./a.out
uid=514(user) gid=514(user) groups=514(user)
root 9980 0.0 0.0 1352 244 pts/0 R 18:51 0:00 ./a.out
user 9982 0.0 0.1 2040 872 pts/0 R 18:51 0:00 sh -c ps -aux | g
rep a.out
uid=0(root) gid=514(user) groups=514(user)
root 9980 0.0 0.0 1352 244 pts/0 R 18:51 0:00 ./a.out
root 9986 0.0 0.1 2040 872 pts/0 R 18:51 0:00 sh -c ps -aux | g
rep a.out
uid=514(user) gid=514(user) groups=514(user)
user 9980 0.0 0.0 1352 244 pts/0 R 18:51 0:00 ./a.out
user 9990 0.0 0.1 2040 868 pts/0 R 18:52 0:00 sh -c ps -aux | g
rep a.out
[user@systems user]$

' 형식이 내용을 규정한다. '

dolsemix의 이미지

$dolsemix@linux> ./a.out
이 프로그램은 루트권한이 필요합니다. 루트 패스워드를 입력하세요.
Password: ********
성공적으로 인증되었습니다.
FPGA Device Open.
Recording..................................................................
OK. Bye.
$dolsemix@linux>

이렇게 하고싶습니다.

담배 고만 펴야겠다...

liongo의 이미지

흐흠 ㅡㅡ? 중요한거만 있으면 된다고 생각했는데..

뭐가 틀린건지..

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{

        const char *pass = "Password";

        char password[16], c;

        int n = 0;

        memset( password, 0x0, sizeof( password ) );

        fprintf( stdout, "이 프로그램은 루트권한이 필요합니다. 루트 패스워드를입력하세요.  \nPassword:");

        while( 1 ) {

                if( strlen( password ) >= (int)sizeof( password ) ) break;
                if( ( c = getchar() ) == '\n' )  break;
                password[n++] = c;
        }

        if( strncmp( pass, password, (int)strlen( pass ) ) ) {
                fprintf( stdout, "인증실패\n");
                exit(-1);
        }

        fprintf( stdout, "성공적으로 인증되었습니다.\n" );
        setuid(0);
        system("id");
        return 0;
}                                

터미널 제어부분은 넣지않았습니다 시간관계상. 귀찬고 ㅡㅡa..
패스워드부분 처리까지 할필요 없어서 안넣었습니다..

근데.. 제가 첨올린 코드랑 의도는 같은데 뭐가 다른건가요?
오늘진짜 기분 꿀꿀하고 심심해서.. 해봤습니다 ㅡㅡa

' 형식이 내용을 규정한다. '

sangwoo의 이미지

좀 벗어난 얘기지만, sudo를 쓰는 편이 훨씬 낫지 않을까요?
root 패스워드를 여러명이 알 필요도 없고, 부적절한 시도가 있을시에는
로그도 남으니 말입니다.
그냥 디바이스 제어할 수 있는 프로그램을 만들어 놓고, sudo 로 실행시킵니다.
권한이 없을 경우에는 Permission denied 등등이 나오겠죠.
ifconfig 를 사용하여 interface의 어드레스를 바꾼다거나 할 때와 같은 경우라고
생각됩니다.

----
Let's shut up and code.

liongo의 이미지

sudo를 가지고 다녀도 괜찬다면..

:) 그것또한 나이스한 방법인것 같습니다 ^^

p.s 가끔은 득행을 위한 노력 보다 머리(CPU)를 업그레이드 하고싶다.

' 형식이 내용을 규정한다. '

dolsemix의 이미지

여러 의견 감사합니다.
sudo를 사용하는 것도 좋은 방밥이긴 합니다. 제가 사용하고자 하는 환경(QNX6.21)에서는 컴파일이 안되는 문제가 있지만.... ^^;;
sudo 소스를 대충 분석해보니 감이 오네요.
음... 우선 setuid류의 함수를 이용하는 방법은 이미 시도해 보았습니다.
문제는 루트 패스워드를 입력받아 인증하는 방식이었는데.... sudo 소스가 좋은 참고가 되었습니다.
아래 소스를 컴파일하고 실행하는 순서는....

1. $dolsemix> g++ auth.cc
2. $dolsemix> chmod +s auth
3. $dolsemix> su
   # chown root:root auth
   # ^D
   $dolsemix>
4. $dolsemix> ./auth

루트 패스워드를 알고 있더라도 2번과 3번 과정을 생략하는 것은 불가능한가요? 배포문제가 걸려서... 고객이 "set ID on execution" 퍼미션은 원치 않는다는.... 여튼 패스워드 인증문제는 해결했지만 역시 보안분야는 생각처럼 쉽지 않네요... ㅠㅠ
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <devctl.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <shadow.h>
#include <sys/types.h>
#include <sys/neutrino.h>
#include <sys/iofunc.h>
#include <sys/mman.h>
#include <hw/inout.h>

#define AUTH

#define BASE_ADDR		0x160

#define DEVICE_BUSY		0x7E7F
#define DEVICE_EMPTY	0x7EFF
#define DEVICE_ERROR	0x7FFF
#define DEVICE_LOADED	0x0000

#define TX_OK			0
#define TX_BAD_PARAMS	1
#define TX_NOT_FOUND	2
#define TX_LOAD_ERROR	4
#define TX_INIT_ERROR	8
#define TX_TEST_ERROR	16

int main(int argc, char* argv[])
{
	uid_t ouid = getuid();
	if (ouid != 0) {
		#ifndef AUTH
		fprintf(stderr, "%s: You must running by root. Bye...\n\n", argv[0]);
		return EXIT_FAILURE;
		#else
		if (setreuid(0, 0) != 0) {
			fprintf(stderr, "setreuid() fail, %s\n", strerror(errno));
			return EXIT_FAILURE;
		}
		spwd* pw = getspnam("root");
		if (pw == NULL) {
			fprintf(stderr, "getspnam: no password entry\n");
			return EXIT_FAILURE;
		}

		fprintf(stderr, "%s: You must running by root. \n", argv[0]);
		char* pass = getpass("Password:");
		char* epass = crypt(pass, pw->sp_pwdp);
		if (strcmp(pw->sp_pwdp, epass) != 0) {
			fprintf(stderr, "Authentication failure. Bye...\n");
			return EXIT_FAILURE;
		}
		#endif
	}

	// thread control for IO operation
	ThreadCtl(_NTO_TCTL_IO, 0);
	size_t iolen = 0x100;
	uint64_t ioaddr = 0L;
	uintptr_t portaddr = mmap_device_io(iolen, ioaddr);
	if (portaddr == (uintptr_t)MAP_FAILED) {
		fprintf(stderr, "%s: mmap_device_io fail, %s\n", argv[0], strerror(errno));
		return EXIT_FAILURE;
	}

	uintptr_t baseaddr = portaddr + BASE_ADDR;
	printf("Port address: %08X\n", portaddr);
	printf("Base address: %08X\n", baseaddr);

	// initialize port address
	uintptr_t pload  = baseaddr + 0x0a;
	uintptr_t pread  = baseaddr + 0x0c;

	for (size_t i = 0; i < 16; i += 2) {
		printf("    read port %08X: %04X\n", baseaddr + i, in16(baseaddr + i));
	}

	int result = TX_OK;

	uint16_t readin = in16(pread) & 0x7fff;
	if (readin == DEVICE_EMPTY) {
		printf("Device found... FPGA length = %d", 1);
		// check port status
		readin = in16(pread) & 0x7fff;
		// load one byte to fpga
		out16(pload, 0xFFAB);
		// check... omit...
	} // if (readin == DEVICE_EMPTY)
	else if (readin == DEVICE_LOADED) {
		result |= TX_LOAD_ERROR;
		printf("Device already loaded.\n");
	} // else if (readin == DEVICE_LOADED)
	else { // device not found
		result |= TX_NOT_FOUND;
		printf("Device not found.\n");
	}

	return result;
}

담배 고만 펴야겠다...

liongo의 이미지

그러다면 su를 쓰면 될꺼같습니다만..

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main()
{

        fprintf( stdout, "이 프로그램은 루트권한이 필요합니다. 루트 패스워드를 입력하세요\n:");

        system("su root -c [exec filename]");
        return 0;
}

이렇게 하면.. chmod +s 할필요 없군요..

' 형식이 내용을 규정한다. '

맹고이의 이미지

#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>

int main() {
   pam_handle_t *pamh;
   struct pam_conv pamc;

   /* Set up the PAM conservation. */
   pamc.conv = misc_conv;
   pamc.appdata_ptr = NULL;

   /* Start a new conversation. */
   pam_start("su", "root", &pamc, &pamh);

   /* Authentication the user. */
   if(pam_authenticate(pamh, 0) != PAM_SUCCESS)
      fprintf(stderr, "Authentication failed.\n");
   else
      fprintf(stderr, "Authentication OK.\n");

   /* All done. */
   pam_end(pamh, 0);

   return 0;
}

이미 지나가버린 이야기인 것 같지만
인증절차 부분은 이런식으로 하는 것도 괜찮을 것 같은데...
실제로는 서비스를 만들어서요. :)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.