在 C#/VB.NET 中解码 T-SQL CAST
题
最近,我们的网站因重新流行而被淹没 Asprox 僵尸网络 SQL注入 攻击。无需详细说明,攻击会尝试通过编码来执行 SQL 代码 T-SQL ASCII 编码的 BINARY 字符串中的命令。它看起来像这样:
DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x44004500...06F007200%20AS%20NVARCHAR(4000));EXEC(@S);--
我能够用 SQL 对其进行解码,但我对此有点谨慎,因为我不知道当时到底发生了什么。
我尝试编写一个简单的解码工具,这样我就可以解码这种类型的文本,甚至无需触摸 SQL 服务器. 。我需要解码的主要部分是:
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 方法时,我得到“,-+”作为结果。
我如何找出我缺少的内容 - 我是否需要对每个字节进行“直接转换”而不是尝试解析它?
解决方案
我回到迈克尔的帖子,做了更多的探索,意识到我确实需要进行双重转换,并最终解决了这个小问题:
Convert.ToString(Convert.ToChar(Int32.Parse(EncodedString.Substring(intParseIndex, 2), System.Globalization.NumberStyles.HexNumber)));
从那里我简单地做了一个循环来2×2地遍历所有字符并将它们“十六进制化”,然后转换为字符串。
对于尼克和其他感兴趣的人,我继续说 发布了我的小应用程序 过去在 代码库. 。请根据需要随意使用/修改。
其他提示
尝试删除 0x
首先然后调用 Encoding.UTF8.GetString
. 。我认为这可能有效。
本质上:0x44004500
去掉 0x,那么两个字节总是一个字符:
44 00 = D
45 00 = E
6F 00 = o
72 00 = r
所以它绝对是一个具有两个字节/字符的 Unicode/UTF 格式。