代码: 全选
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char** argv)
{
int socketfd;
uid_t ruid;
struct sockaddr_in servaddr;
if(argc != 2)
exit(1);
if((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror("socket"), exit(1);
memset(&servaddr, 0, sizeof servaddr);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(argv[1]));
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
ruid = getuid();
if((seteuid(0)) < 0)
perror("seteuid"), exit(1);
if((bind(socketfd, (struct sockaddr *)&servaddr, sizeof servaddr)) < 0)
perror("bind"), exit(1);
if((seteuid(ruid)) < 0)
perror("seteuid"), exit(1);
if((listen(socketfd, 1)) < 0)
perror("listen"), exit(1);
while(1){
int connectd_fd;
int n;
char buf[4096];
if((connectd_fd = accept(socketfd, (struct sockaddr *)NULL, NULL))
< 0)
perror("connect"), exit(1);
while((n = recv(connectd_fd, buf, 4096, 0)) > 0){
buf[n] = '\0';
puts(buf);
}
if(n == 0)
fprintf(stderr, "%s", "Connection Closed.\n");
else
perror("recv"), exit(1);
}
return 0;
}
示例代码,写得比较随意,楼主可以自行研究
1. 端口数大于1024时一切正常
2. 端口数小于1024时,把seteuid的东西注释掉,bind就会报告权限不足
3. 把还原euid的代码注释掉,进程owner就会变成root
4. euid还原后,还是可以正常使用特权端口的
5. 如果不做chown和chmod,seteuid会报告权限不足
编译
代码: 全选
cc foo.c -Wall
sudo chown root:root a.out
sudo chmod +s a.out
apache的做法,以root权限载入一个进程,然后fork出一个,再setuid降低权限等级,于是就安全了,楼主可以自己试着写写看