구축 환경
VirtualBox - Fedora 15 (kernel : 2.6.40.4-5.fc15.i686.PAE)
작동 원리
chroot유저 ssh 접속 -> 접속유저의 홈디렉토리 밑 .ssh의 rc 파일 실행 -> daemonstart실행 -> daemon 작동 -> 접속 유저만의 Jail 디렉토리 생성 -> 접속 유저의 .bashrc 의 chroot 명령어 실행 -> V_Jail 접속 완료
chroot 구축에 필요한 파일 목록
/chroot/bin/
/chroot/dev/ : null zero
/chroot/home/ : Jail을 이용할 사용자 홈디렉토리
/chroot/lib/
/chroot/etc/
/chroot/usr/bin/
/chroot/usr/lib/
/chroot/usr/share/ (아래 두 디렉토리를 원본그대로 Copy )
V_Jail - Daemon & Daemonstart Code & fifo.h Code
- fifo.h -
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define SV_FIFO_NAME "/tmp/fifo/sv_fifo"
#define CL_FIFO_NAME "/tmp/fifo/cl_%d_fifo"
struct data_to_pass_st
{
pid_t client_pid;
};
- Daemon.c -
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include "fifo.h"
#include <ctype.h>
void hand(int signum);
int main()
{
pid_t pid;
if (( pid = fork()) < 0)
{
exit(0);
}
else if(pid != 0)
{
exit(0);
}
signal(SIGHUP, SIG_IGN);
close(0);
close(1);
close(2);
setsid();
while(1)
{
struct sigaction act;
sigset_t set;
sigemptyset(&(act.sa_mask));
sigaddset(&(act.sa_mask), SIGUSR1);
act.sa_handler = hand;
sigaction(SIGUSR1, &act, NULL);
sleep(1);
}
}
void hand(int signum)
{
if(signum == SIGUSR1)
{
int sv_fifo_fd, cl_fifo_fd;
struct data_to_pass_st fifo_data;
int read_res;
char cl_fifo[256];
char path_1[128];
char path_2[128];
char mnt[128]; //아래 이미지에 없는 것. 새로 추가됨
mkfifo(SV_FIFO_NAME, 0777);
sv_fifo_fd = open(SV_FIFO_NAME, O_RDONLY);
if (sv_fifo_fd == -1)
{
exit(EXIT_FAILURE);
}
while(1)
{
read_res = read(sv_fifo_fd, &fifo_data, sizeof(fifo_data));
if (read_res > 0)
{
sprintf(cl_fifo, CL_FIFO_NAME, fifo_data.client_pid);
cl_fifo_fd = open(cl_fifo, O_WRONLY);
if(cl_fifo_fd != -1)
{
sprintf(path_1, "mkdir /V_Jail/%d", fifo_data.client_pid);
sprintf(path_2, "cp –rfp /chroot/* /V_Jail/%d", fifo_data.client_pid);
sprintf(mnt, "mount -t proc /proc/ /V_Jail/%d/proc", fifo_data.client_pid); //아래 이미지에 없는 것. 새로 추가됨
system(path_1);
system(path_2);
system(mnt);
write(cl_fifo_fd, &fifo_data, sizeof(fifo_data));
close(cl_fifo_fd);
}
}
}
close(sv_fifo_fd);
unlink(SV_FIFO_NAME);
exit(EXIT_SUCCESS);
}
}
- Daemonstart.c –
#include "fifo.h"
#include <ctype.h>
int main()
{
system("sudo kill -10 1234"); // 1234란에는 Daemon 의 PID 입력
int sv_fifo_fd, cl_fifo_fd;
struct data_to_pass_st fifo_data;
char cl_fifo[256];
sv_fifo_fd = open(SV_FIFO_NAME, O_WRONLY);
if(sv_fifo_fd == 1)
{
printf("Fail_1");
exit(EXIT_FAILURE);
}
fifo_data.client_pid = getppid();
sprintf(cl_fifo, CL_FIFO_NAME, fifo_data.client_pid);
if(mkfifo(cl_fifo, 0777) == -1)
{
printf("Fail_2");
exit(EXIT_FAILURE);
}
write(sv_fifo_fd, &fifo_data, sizeof(fifo_data));
cl_fifo_fd = open(cl_fifo, O_RDONLY);
if(cl_fifo_fd != -1)
{
if(read(cl_fifo_fd, &fifo_data, sizeof(fifo_data)) > 0 )
{
//이 부분은 IPS가 성공했을 때 실행할 코드
}
close(cl_fifo_fd);
}
close(sv_fifo_fd);
unlink(cl_fifo);
exit(EXIT_SUCCESS);
}
V_Jail을 사용할 사용자의 rc(~/.ssh/rc) Code & .bashrc
- rc –
#!/bin/bash
trap "" 2 3 9
echo "Connecting....Please Wait..."
sudo /home/chroottest/.ssh/fifotest2 &
# 위 경로는 fifotest2 가 있는 경로로 바꿀 수 있음.
while [ 1 ]
do
if [ -d /V_Jail/$! ] && [ -e /V_Jail/$!/etc/passwd ] && [ -d /V_Jail/$!/home/chroottest ] && [ -d /V_Jail/$!/usr/share/vim/vimfiles/tutor ] && [ -e /V_Jail/$!/usr/bin/whoami ]
then
echo "Welcome !!"
echo $! > ./.ssh/ppid
break;
fi
done
- .bashrc -
# .bashrc
trap "" 2 3 9
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
var=$(echo $SSH_TTY | awk -F/ '{print $4}')
ppid=$(cat .ssh/ppid_$var)
chroot --userspec=chroottest:Jail /V_Jail/$ppid /bin/bash
# --userspec의 내용은 사용할 사용자의 정보로 바꾸어야함
visudo 의 추가내용
chroottest ALL=NOPASSWD:/bin/kill, NOPASSWD:/home/chroottest/.ssh/fifotest2, NOPASSWD:/bin/chown, NOPASSWD:/bin/chmod
V_Jail을 사용할 사용자의 rc(~/.ssh/rc) Code(수정 : 종료기 추가)
- rc – (if문 안에 있는 echo들은 빼도 상관없음)
#!/bin/bash
trap "echo Warning! Invalid Command!" 2 3 9
echo "Connecting....Please Wait..."
sudo /home/ctest/.ssh/connecter-1.0 &
var=$(echo $SSH_TTY | awk -F/ '{print $4}')
echo $! > .ssh/ppid_$var
while [ 1 ]
do
if [ -d /V_Jail/$! ] && [ -e /V_Jail/$!/etc/passwd ] && [ -d /V_Jail/$!/home/chroottest ] && [ -d /V_Jail/$!/usr/share/vim/vimfiles/tutor ] && [ -e /V_Jail/$!/usr/bin/whoami ]
then
#exit 만드는 부분
#var=$(echo $SSH_TTY | awk -F/ '{print $4}')
echo "1"
ptsnum=$(echo $SSH_TTY | awk -F/ '{print $4}')
echo "2"
ptsps=$(ps -ef | grep pts/"$ptsnum" | grep sshd | awk '{print $2}' | head -1)
echo "3"
cp /home/ctest/exitfirst.c /V_Jail/$!/bin/
echo "3-2"
sed "s/ptsps/$ptsps/g" /V_Jail/$!/bin/exitfirst.c > /V_Jail/$!/bin/exitsecond.c
echo "4"
gcc -o /V_Jail/$!/bin/exit /V_Jail/$!/bin/exitsecond.c
echo "5"
rm -rf /V_Jail/$!/bin/exitfirst.c /V_Jail/$!/bin/exitsecond.c
echo "6"
sudo chmod o-w /V_Jail/$!/bin
break;
fi
done
* 여기까지 접속 관련 *
* 주의 : V_Jail이란 디렉토리와 chroot라는 디렉토리는 / 밑에 있음 *
* 주의 : /chroot/ 안에는 맨 위의 필요한 파일들이 들어 있어야함 *
* 주의 : /V_Jail/ 퍼미션 주의 *
* 참고 : /chroot/bin 퍼미션은 757 이어야함(접속 계정 권한 문제) *