当前位置:主页 > 查看内容

Alien Swarm中糟糕的远程代码执行

发布时间:2021-05-11 00:00| 位朋友查看

简介:Alien Swarm最初是免费游戏,大约于2010年7月发行。它与大多数Source Engine游戏不同,它是自上而下的射击游戏,尽管其游戏元素与《 Left 4 Dead》并无不同。跌倒了,一个小而敬业的社区使用Alien Swarm:Reactive Drop扩展了游戏。该游戏在高峰时期平均每天……

Alien Swarm最初是免费游戏,大约于2010年7月发行。它与大多数Source Engine游戏不同,它是自上而下的射击游戏,尽管其游戏元素与《 Left 4 Dead》并无不同。跌倒了,一个小而敬业的社区使用Alien Swarm:Reactive Drop扩展了游戏。该游戏在高峰时期平均每天约有800个用户,并且仍在积极更新中。

十多年前,Source和GoldSrc标题中存在多个逻辑错误,从而允许从客户端到服务器执行任意代码,反之亦然,从而使插件被窃取或从客户端到服务器写入任意数据,反之亦然。我们将在Alien Swarm:Reactive Drop中探索一个现代的例子。

客户端<->服务器文件上传

任何异形丛生客户端可以上传使用文件到游戏服务器(并且反之亦然)CNetChan->SendFile的API,但仍存在一些可疑约束:客户端检查在游戏阻止某些扩展,例如上载文件的服务器.dll.cfg

if ( (!(*(unsigned __int8 (__thiscall **)(int, char *, _DWORD))(*(_DWORD *)(dword_104153C8 + 4) + 40))(
         dword_104153C8 + 4,
         filename,
         0)
   || should_redownload_file((int)filename))
  && !strstr(filename, "//")
  && !strstr(filename, "\\\\")
  && !strstr(filename, ":")
  && !strstr(filename, "lua/")
  && !strstr(filename, "gamemodes/")
  && !strstr(filename, "addons/")
  && !strstr(filename, "..")
  && CNetChan::IsValidFileForTransfer(filename) ) // fails if filename ends with ".dll" and more
{ /* accept file */ }
bool CNetChan::IsValidFileForTransfer( const char *input_path )
{
    char fixed_slashes[260];

    if (!input_path || !input_path[0])
        return false;

    int l = strlen(input_path);
    if (l >= sizeof(fixed_slashes))
        return false;

    strncpy(fixed_slashes, input_path, sizeof(fixed_slashes));
    FixSlashes(fixed_slashes, '/');
    if (fixed_slashes[l-1] == '/')
        return false;

    if (
        stristr(input_path, "lua/")
        || stristr(input_path, "gamemodes/")
        || stristr(input_path, "scripts/")
        || stristr(input_path, "addons/")
        || stristr(input_path, "cfg/")
        || stristr(input_path, "~/")
        || stristr(input_path, "gamemodes.txt")
        )
        return false;

    const char *ext = strrchr(input_path, '.');
    if (!ext)
        return false;

    int ext_len = strlen(ext);
    if (ext_len > 4 || ext_len < 3)
        return false;

    const char *check = ext;
    while (*check)
    {
        if (isspace(*check))
            return false;

        ++check;
    }

    if (!stricmp(ext, ".cfg") ||
        !stricmp(ext, ".lst") ||
        !stricmp(ext, ".lmp") ||
        !stricmp(ext, ".exe") ||
        !stricmp(ext, ".vbs") ||
        !stricmp(ext, ".com") ||
        !stricmp(ext, ".bat") ||
        !stricmp(ext, ".dll") ||
        !stricmp(ext, ".ini") ||
        !stricmp(ext, ".log") ||
        !stricmp(ext, ".lua") ||
        !stricmp(ext, ".nut") ||
        !stricmp(ext, ".vdf") ||
        !stricmp(ext, ".smx") ||
        !stricmp(ext, ".gcf") ||
        !stricmp(ext, ".sys"))
        return false;

    return true;
}

旁路"//" and ".."是可以做到的"/\\",因为那里是FixSlashes一个电话,让适当的斜杠的完整性检查,并在"..""/\\"会的路径设置为驱动器的根,这样我们就可以写入系统上的任何地方,如果我们知道路径。"lua/", "gamemodes/" and "addons/"可以通过使用大写字母来绕过,例如,"ADDONS/"因为Windows上的文件路径不区分大小写。

绕过文件扩展名检查比较麻烦一些,所以让我们看看结构通过发送SendFile名为dataFragments_t

typedef struct dataFragments_s
{
    FileHandle_t    file;                 // open file handle
    char            filename[260];        // filename
    char*           buffer;               // if NULL it's a file
    unsigned int    bytes;                // size in bytes
    unsigned int    bits;                 // size in bits
    unsigned int    transferID;           // only for files
    bool            isCompressed;         // true if data is bzip compressed
    unsigned int    nUncompressedSize;    // full size in bytes
    bool            isReplayDemo;         // if it's a file, is it a replay .dem file?
    int             numFragments;         // number of total fragments
    int             ackedFragments;       // number of fragments send & acknowledged
    int             pendingFragments;     // number of fragments send, but not acknowledged yet
} dataFragments_t;

其中的260个字节的名称缓冲区dataFragments_t用于文件名检查和过滤器,但随后进行复制,然后在进行完所有检查后将其截断为256个字节,从而删除了我们的假扩展名并激活了恶意扩展名:

Q_strncpy( rc->gamePath, gamePath, BufferSize /* BufferSize = 256 */ );

在检查文件扩展名是否有效之后,在接收端使用诸如./././(...)/file.dll.txt(用填充至最大长度./)之类的文件名会被截断为./././(...)/file.dll。这还有一个副作用,我们可以在文件扩展名被截断之前检查文件是否存在,从而覆盖文件。

远程执行代码

使用前面提到的远程文件包含,我们可以上传有可能执行任意代码的Source Engine配置文件。使用Procmon,我发现游戏引擎分别在platform/cfg和两者中搜索配置文件swarm/cfg

我们可以简单地将恶意插件和配置文件上传到platform/cfg服务器并对其进行劫持。这是由于Source Engine服务器配置具有使用以下plugin_load命令加载插件的能力:

plugin_load addons/alien_swarm_exploit.dll

这会将我们的动态库加载到游戏服务器应用程序中,从而允许执行任意代码。唯一的限制是newmapsettings.cfg配置文件仅在地图更改时重新加载,因此您必须等到游戏结束。

糟糕的示范

由于这两种漏洞利用都适用于服务器和客户端,因此我们可以感染服务器,这可以感染所有播放器,当播放其他服务器时,这些播放器可能会继续感染病毒。这使得该漏洞利用链完全可蠕虫入侵,只有完全关闭游戏服务器才能修复该漏洞利用链。


本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!
上一篇:Unity中的Vector3.Dot()方法详解 下一篇:没有了

推荐图文

  • 周排行
  • 月排行
  • 总排行

随机推荐