Linux

root가 아닌 유저에 의해 실행된 프로세스가 socket을 열 수 없을 때

behonestar 2015. 2. 15. 11:31

증상


vsftpd를 사용하여 ftp server를 열었으나 client에서 디렉토리 목록 조회가 불가능



vsftp server쪽 socket 생성 시 permission denied.

/* 부모 프로세스 */

vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess)

{

  // 자식 프로세스로 cmd 전송

  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_GET_DATA_SOCK); 


  // 포트 전송

  priv_sock_send_int(p_sess->child_fd, port);


  res = priv_sock_get_result(p_sess->child_fd);

}




/* 자식 프로세스 */

process_post_login_req(struct vsf_session* p_sess)

{

  // 부모 프로세스로부터 cmd 수신

  cmd = priv_sock_get_cmd(p_sess->parent_fd);

  ...


  else if (cmd == PRIV_SOCK_GET_DATA_SOCK)

  {

    cmd_process_get_data_sock(p_sess);

  }

  ...

}


cmd_process_get_data_sock(struct vsf_session* p_sess)

{

  // 포트 수신

  port = (unsigned short) priv_sock_get_int(p_sess->parent_fd);


  // 소켓 생성 

  sock_fd = vsf_privop_get_ftp_port_sock(p_sess, port, 0);

      vsf_sysutil_get_ipsock(p_sess->p_local_addr);

        socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //permission denied

          die("socket"); // 소켓 생성 실패하면 자식 프로세스 exit

}




원인


커널 옵션 중 CONFIG_ANDROID_PARANOID_NETWORK = y 일 때는 특정 유저 그룹(aid_inet)에 속한 사용자만 socket을 생성할 수 있다.


vsftpd는 특정 user 계정으로 자식 프로세스를 생성하여 ftp 디렉토리 접근 권한 등을 관리한다. 해당 user가 socket 생성 권한이 없는 유저 그룹이기 때문에 문제가 발생하였다.



대책1


aid_inet 그룹을 생성하고, 유저의 그룹을 변경

/etc/group 생성 (또는 groupadd -g 3003 aid_inet)

root::0:nobody,ftp,ADMIN

messagebus:x:18:messagebus

aid_inet:x:3003:


/etc/passwd 편집 (신규 user 생성 시 그룹을 aid_inet으로 설정)

root:$1$$qRPK7m23GJusamGpoGLby/:0:0::/root:/bin/sh

messagebus:x:18:18:Linux User,,,:/var/run/dbus:/bin/false

nobody:x:1000:3003:Linux User,,,:/home/nobody:/bin/sh

ftp:x:1001:3003:Linux User,,,:/home/ftp/bin/sh

ADMIN:O9UN.3.wi4hjg:1002:3003:Linux User,,,:/home/ftproot:/bin/sh



대책2


권한이 없는 유저에 의해 실행된 프로세스도 socket을 열 수 있도록 커널 옵션 변경

# make ARCH=arm menuconfig

-> Networking support

   -> Networking options

      -> Only allow certain groups to create sockets //사용하지 않도록


# vi security/commoncap.c

int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,

                int cap, int audit)

{

#ifdef CONFIG_ANDROID_PARANOID_NETWORK // 추가

        if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW))

                return 0;

        if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))

                return 0;

#endif // 추가


참조

[SLUG] non-root users cant use network [FIXED]