在C#/VB.NET中解析T-SQL CAST

68

最近我们的网站受到了Asprox botnet SQL注入攻击的困扰。不详细介绍,该攻击尝试通过将T-SQL命令编码为ASCII编码的二进制字符串来执行SQL代码。它看起来像这样:

DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x44004500...06F007200%20AS%20NVARCHAR(4000));EXEC(@S);--

我能够在 SQL 中解码这个,但我当时有些担心,因为我不知道当时到底发生了什么。
我尝试编写一个简单的解码工具,以便可以在不接触 SQL Server 的情况下对这种文本进行解码。需要解码的主要部分是:
CAST(0x44004500...06F007200 AS
NVARCHAR(4000))

我已尝试了以下所有命令,但都没有成功:

txtDecodedText.Text =
    System.Web.HttpUtility.UrlDecode(txtURLText.Text);
txtDecodedText.Text =
    Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(txtURLText.Text));
txtDecodedText.Text =
    Encoding.Unicode.GetString(Encoding.Unicode.GetBytes(txtURLText.Text));
txtDecodedText.Text =
    Encoding.ASCII.GetString(Encoding.Unicode.GetBytes(txtURLText.Text));
txtDecodedText.Text =
    Encoding.Unicode.GetString(Convert.FromBase64String(txtURLText.Text));

如果不使用SQL Server,那么正确的编码翻译方式是什么?这可行吗?我可以用VB.NET代码,因为我对它比较熟悉。


好的,我确定我在这里漏掉了一些东西,所以这就是我的现状。

由于我的输入只是一个基本字符串,所以我从编码部分的简短片段开始 - 4445434C41(转换为DECLA)- 第一次尝试是这样做的...

txtDecodedText.Text = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(txtURL.Text));

...它只是返回我输入的完全相同的东西,因为它将每个字符转换为一个字节。

我意识到我需要手动将每两个字符解析为一个字节,因为我还不知道有任何方法可以这样做,所以现在我的小解码器看起来像这样:

while (!boolIsDone)
{
    bytURLChar = byte.Parse(txtURLText.Text.Substring(intParseIndex, 2));
    bytURL[intURLIndex] = bytURLChar;
    intParseIndex += 2;
    intURLIndex++;

    if (txtURLText.Text.Length - intParseIndex < 2)
    {
        boolIsDone = true;
    }
}

txtDecodedText.Text = Encoding.UTF8.GetString(bytURL);

首先几对看起来很好,但是当循环到"4C"这一对时,程序就会停止并提示字符串格式不正确。

有趣的是,当我通过调试器逐步跟踪到能够解析的字节数组的GetString方法时,结果显示为",-+"。

我该如何找出自己缺少什么 - 我需要为每个字节进行"直接转换"而不是尝试解析它吗?


是的,如果你还没有使用SQL参数,我肯定会建议你从这里开始。 - EndangeredMassa
看看我在这里的回答:https://dev59.com/wUXRa4cB1Zd3GeqPogs2 - SQLMenace
我尽力尝试整理一些“答案”,但其中大部分根本不是答案。因此,将其他非答案转换为非答案的评论是不可能的,因此这些被转换为评论。如果我有任何错误,请告诉我。 - Tim Post
2个回答

24

我回到了Michael的帖子,进行了更多的探究,并意识到我需要进行双重转换,最终想出了这个小技巧:

Convert.ToString(Convert.ToChar(Int32.Parse(EncodedString.Substring(intParseIndex, 2), System.Globalization.NumberStyles.HexNumber)));

从这里,我只需创建一个循环逐个处理每两个字符并将其转换为十六进制,然后再转换为字符串。

对于Nick和其他有兴趣的人,我已经在CodePlex发布了我的小应用程序。请随意使用/修改。


8

尝试先移除0x,然后调用Encoding.UTF8.GetString。我认为这样可能会起作用。

本质上:0x44004500

移除0x,然后每两个字节组成一个字符:

44 00 = D

45 00 = E

6F 00 = o

72 00 = r

因此,它肯定是一个每个字符有两个字节的Unicode/UTF格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接