服务器是:LINUX_APACHE
想写一个HTML,提交一个IP 地址,然后,后台的CGI将这台服务器的IP地址用ifconfig改掉。
理论上分析,好似比较简单:只要写一个shell脚本,调用ifconfig来改IP地址就可以了。由于更改IP地址需要root权限才能完成,所以,将这个shell给他s权限即可。
以上好象没有问题,但是忽略了一个问题:对shell脚本给定s权限是达不到目的的,只能对二进制s才行,因此下面借用了一个C程序来完成权限的提升。
index.html
<html>
<head>
<title>test</title>
</head>
<body>
<form action="/cgi-bin/allroot" method="get">
<input type="text" name="var_ip">
<input type="submit" >
</form>
</body>
页面提交后,交由一个C写的程序allroot。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
uid_t uid ,euid;
uid = getuid() ;
euid = geteuid();
if(setreuid(euid, uid)) //交换这两个id
perror("setreuid");
system("/var/www/cgi-bin/changeip.sh");
return 0;
}
该程序并没做任何事情,只是调用了一个脚本而已。但是这个C是必须的,它是a+s属性,接下来执行的shell是具有超级用户权限的。注意:用户提交的数据放在一个环境变量里,例如:QUERY_STRING=var_ip=1.1.1.1,这个变量会一直往下继承。
上面的C程序只是起到一个提升至ROOT权限的功能,具体实现是由下面的脚本来完成的。
#!/bin/bash
ip=`echo $QUERY_STRING | awk -F '=' '{print $2}'`
ifconfig eth0 $ip
上面的脚本将var_ip提交过来的IP地址应用到ifconfig语句中。这样就完成了对主机IP地址的更改。
下面是一个完整的更改IP地址的脚本程序(支持POST方式,避免了GET方式的不安全)
#!/bin/bash
#if the program what called this cgi isn't sysconf.php, this script will refuse to run!!!!
#如果不是通过sysconf.php调用这个脚本,则拒绝执行,以保证安全性,避免直接通过http加参数的get
#方式直接运行
if [ -z `echo $HTTP_REFERER | sed -n '/sysconf.php/p'` ] ; then
exit
fi
if [ $REQUEST_METHOD = "POST" ]; then
QUERY_STRING=`cat /dev/stdin`
fi
echo "Content-type:text/html"
echo ""
eth0_cfg="/etc/sysconfig/network-scripts/ifcfg-eth0"
var_ip=`echo $QUERY_STRING | awk -F '&' '{print $1}' | awk -F '=' '{print $2}'`
var_mask=`echo $QUERY_STRING | awk -F '&' '{print $2}' | awk -F '=' '{print $2}'`
var_gateway=`echo $QUERY_STRING | awk -F '&' '{print $3}' | awk -F '=' '{print $2}'`
sed -i '/^NETMASK/d' $eth0_cfg
sed -i '/^IPADDR/d' $eth0_cfg
sed -i '/^GATEWAY/d' $eth0_cfg
echo "IPADDR=$var_ip" >> $eth0_cfg
echo "NETMASK=$var_mask" >> $eth0_cfg
echo "GATEWAY=$var_gateway" >> $eth0_cfg
#ifconfig eth0 $var_ip netmask $var_mask
#route add default gw $var_gateway
echo "Successful!Pls reboot now"
mysql -uroot -proot <<EOF
use peter;
insert into setting (key_var,value) values ("888222","333");
EOF