http访问拦截器,过滤xxs构建的请求
public class HttpAccessInterceptModule : IHttpModule
{
private static List<string> _RegexWords;
static HttpAccessInterceptModule()
{
_RegexWords = new List<string>()
{
@"<[^>]+>'",
@"</[^>]+>'",
@"<[^>]+?style=[\w]+?:expression\(|\b(alert|confirm|prompt|window|location|eval|console|debugger|Function|var|let)\b|^\+/v(8|9)|<[^>]*?=[^>]*?&#[^>]*?>|\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|/\*.+?\*/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"
};
}
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += OnPreSendRequestHeaders;
context.BeginRequest += Context_BeginRequest;
}
private void OnPreSendRequestHeaders(object sender, EventArgs e)
{
try
{
if (sender is HttpApplication app)
{
app.Response.Headers.Set("Server", "WebServer");
app.Response.Headers.Remove("X-AspNet-Version");
app.Response.Headers.Remove("X-AspNetMvc-Version");
app.Response.Headers.Remove("X-Powered-By");
}
}
catch (Exception ex)
{
Log.Error(this, ex);
}
}
private void Context_BeginRequest(object sender, EventArgs e)
{
if (sender is HttpApplication app)
{
try
{
RequestFiller(app);
}
catch (Exception ex)
{
Log.Error(this, ex);
app.Response.StatusCode = (int)HttpStatusCode.Forbidden;
app.Response.StatusDescription = HttpStatusCode.Forbidden.ToString();
app.Response.ContentType = "text/plain; charset=utf-8";
app.Response.ContentEncoding = Encoding.UTF8;
app.Response.Write("[ERROR][-1]操作失败,请求无法通过");
app.Response.End();
}
}
}
private void RequestFiller(HttpApplication app)
{
HttpRequest request = app.Request;
WebUtils.GetClientHostAndAddress(request, out var userHostName, out var userHostIp);
foreach (string key in request.Params.AllKeys)
{
string value = request.Params[key];
if (!string.IsNullOrWhiteSpace(value) && key == "data")
{
value = app.Server.HtmlDecode(value);
}
if (!string.IsNullOrWhiteSpace(key))
{
foreach (string regex in _RegexWords)
{
if (Regex.IsMatch(key, regex, RegexOptions.IgnoreCase))
throw new BaseException($"存在访问风险,参数[{key}={value}]无法通过“{regex}”校验。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
}
}
if (!string.IsNullOrWhiteSpace(value))
{
foreach (string regex in _RegexWords)
{
if (Regex.IsMatch(value, regex, RegexOptions.IgnoreCase))
throw new BaseException($"存在访问风险,参数[{key}={value}]无法通过“{regex}”校验。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
}
}
}
if (request.Files.Count > 0)
{
foreach (string filesAllKey in request.Files.AllKeys)
{
var fileData = request.Files[filesAllKey];
if (fileData == null || fileData.ContentLength == 0)
continue;
var exName = System.IO.Path.GetExtension(fileData.FileName);
if (!exName.IsCanUp())
throw new BaseException($"上传失败,不支持的文件扩展名[{exName}]。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
var bytes = new byte[160];
fileData.InputStream.Read(bytes, 0, bytes.Length);
fileData.InputStream.Position = 0;
var pass = FileTypeCheck.IsValidFileExtension(fileData.FileName, bytes);
if (!pass)
throw new BaseException($"上传失败,[{fileData.FileName}]的文件格式不正确。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
if (exName.ToLower().Contains("rar") || exName.ToLower().Contains("zip"))
{
var option = new ReaderOptions();
var encod = new ArchiveEncoding();
encod.Default = Encoding.Default;
option.ArchiveEncoding = encod;
var archive = ArchiveFactory.Open(fileData.InputStream, option);
foreach (var entry in archive.Entries)
{
if (!entry.IsDirectory)
{
string exTemp = System.IO.Path.GetExtension(entry.Key);
if (!exTemp.IsCanUp())
throw new BaseException($"上传失败,压缩文件内容格式错误,不支持的文件扩展名[{exTemp}]。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
var ms = new MemoryStream();
entry.WriteTo(ms);
pass = FileTypeCheck.IsValidFileExtension(entry.Key, ms.GetBuffer());
if (!pass)
throw new BaseException($"上传失败,压缩文件内容[{entry.Key}]的文件格式不正确。远程客户端信息[{userHostName},{userHostIp}],请求地址[{request.Url}]。");
ms.Dispose();
}
}
fileData.InputStream.Position = 0;
}
}
}
}
}
在web.config的system.webServer节点下增加
<modules runAllManagedModulesForAllRequests="true">
<remove name="HttpAccessInterceptModule"/>
<add name="HttpAccessInterceptModule" type="Core.Commons.HttpAccessInterceptModule, Core.Commons"/>
</modules>
|