0x01. 漏洞描述
4月26日在twitter上看到Orange师傅发布了个windows事件查看器的 .Net 反序列化漏洞,感觉有点意思,故抽空简单做个复现与分析。
0x02. 漏洞复现
- 测试环境:Windows 11,ARM版
ysoserial.exe -o raw -f BinaryFormatter -g DataSet -c calc > %LOCALAPPDATA%\Microsoft\Eventv~1\RecentViews
其中,%LOCALAPPDATA% 对应路径为:C:\Users\xxx\AppData\Local,xxx为用户名,
不过本人机器上并没有 Eventv~1 这个目录,遂用 Event Viewer 目录代替,经测试也可以成功。
对应Payload为:
ysoserial.exe -o raw -f BinaryFormatter -g DataSet -c calc > "%LOCALAPPDATA%\Microsoft\Event Viewer\RecentViews"
PS:后面的路径注意要用双引号括起来,不然会因为Event Viewer目录中有空格导致写入不成功。
然后终端执行 eventvwr 命令即可看到计算器弹出来:
0x03. 漏洞分析
终端执行 eventvwr命令后,使用 Process Monitor 查看进程树如下:
可以看到 eventvwr 启动了 mmc.exe
使用 Process Explorer 查看mmc.exe启动时调用的 .net程序集(需要管理员权限):
可以看到调用了 EventViewer.ni.dll,找到该文件,使用 ILSpy 反编译该dll,大概看了下代码,发现类 EventViewerHomepage 应该是入口类,如下:
跟进 EventHomeControl 类,该类的初始化方法如下:
跟进 UpdateUI 方法,如下,由payload可知关注case 1即可:
UpdateRecentViewsUI 方法中调用了 UpdateRecentViewsListViewUI,继续跟进该方法:
看了下UpdateRecentViewsListViewUI 方法中并没有值得关注的地方,故将注意力转到传递给该方法的参数 RecentViewsDataArrayList:
可以看到其是 EventsNode 类中的一个变量,进入 EventsNode类:
接着跟进 LoadDataForRecentViews 方法,发现其又调用了 LoadMostRecentViewsDataFromFile方法,如下:
在 LoadMostRecentViewsDataFromFile方法中,先获取 recentViewsFile 的文件流并对其执行了反序列化操作,这样正常情况下便可获得最近的事件日志列表数组:
跟进 recentViewsFile,看看其如何获取:
上述代码中变量与常量的值分别如下:
- Environment.SpecialFolder.CommonApplicationData 在Windows系统里表示 “C:\Users\用户名\AppData\Roaming”
- internal static string MicrosoftFolderName = “Microsoft”;
- internal static string LIN_EventViewer = “Event Viewer”;
- LocalApplicationData代表 " C:\Users\用户名\AppData\Local ";
- public static readonly char DirectorySeparatorChar = ‘\’;
所以最终 recentViewsFile 的值为: C:\Users\用户名\AppData\Local\Microsoft\Event Viewer\RecentViews
故payload需要写入文件名为 RecentViews 的文件中,且该文件名是固定的。