Incapsula拦截含危险标签HTML文件上传的代码优化咨询
没问题,既然改不了Incapsula的规则,那咱们就从上传内容本身下手——核心思路就是让Incapsula读不懂上传的文件内容,自然就不会触发拦截。给你两个可行的方案,结合你的VB代码来改:
方案1:Base64编码上传(最易实现)
Base64会把所有二进制内容转换成纯文本字符,Incapsula没法把这些字符识别成<script>这类HTML危险标签。只需要在客户端上传前把文件编码成Base64,服务器端接收后再解码还原就行。
客户端代码修改
把原来直接上传文件流的逻辑,改成先编码再上传:
' 替换你原来的UploadHTMLFile调用代码 Dim fileContent As Byte() = New Byte(ofd.File.Length - 1) {} Using fileStream As Stream = ofd.File.OpenRead() fileStream.Read(fileContent, 0, fileContent.Length) End Using ' 转成Base64字符串再转成流 Dim base64Str As String = Convert.ToBase64String(fileContent) Dim encodedStream As New MemoryStream(Encoding.UTF8.GetBytes(base64Str)) ' 给文件名加个.base64后缀,方便服务器识别是编码后的文件 UploadHTMLFile(ofd.File.Name & ".base64", encodedStream)
服务器端(myreceiver.ashx)修改
接收后先解码再保存原文件:
Public Class myreceiver : Implements IHttpHandler Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim fileName As String = context.Request.QueryString("filename") ' 去掉后缀还原原文件名 If fileName.EndsWith(".base64") Then fileName = fileName.Substring(0, fileName.Length - 7) End If Using inputStream As Stream = context.Request.InputStream Dim reader As New StreamReader(inputStream) Dim base64Content As String = reader.ReadToEnd() ' 解码回原文件字节 Dim originalBytes As Byte() = Convert.FromBase64String(base64Content) Dim savePath As String = Path.Combine("你的服务器存储目录", fileName) File.WriteAllBytes(savePath, originalBytes) End Using End Sub ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class
方案2:AES对称加密上传(安全性更高)
如果担心Base64编码后的内容还是可能被WAF识别(概率极低),可以用AES加密。客户端加密后上传,服务器端用相同密钥解密,WAF看到的是乱码一样的加密内容,完全不会触发规则。
客户端加密辅助函数+上传修改
先写一个加密流的工具函数:
Private Function EncryptStream(inputStream As Stream, key As Byte(), iv As Byte()) As Stream Dim aes As New AesManaged() aes.Key = key aes.IV = iv Dim encryptor As ICryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV) Dim encryptedMs As New MemoryStream() Using cryptoStream As New CryptoStream(encryptedMs, encryptor, CryptoStreamMode.Write) inputStream.CopyTo(cryptoStream) cryptoStream.FlushFinalBlock() End Using encryptedMs.Position = 0 ' 重置流位置以便读取 Return encryptedMs End Function
然后修改上传逻辑:
' 密钥和IV要和服务器端完全一致,建议从配置文件读取,不要硬编码 Dim aesKey As Byte() = Encoding.UTF8.GetBytes("你的32位密钥(AES-256要求)") Dim aesIV As Byte() = Encoding.UTF8.GetBytes("你的16位初始化向量") Using originalStream As Stream = ofd.File.OpenRead() Dim encryptedStream As Stream = EncryptStream(originalStream, aesKey, aesIV) ' 加.encrypted后缀标识加密文件 UploadHTMLFile(ofd.File.Name & ".encrypted", encryptedStream) End Using
服务器端解密+保存修改
在myreceiver.ashx里加解密函数:
Private Function DecryptStream(inputStream As Stream, key As Byte(), iv As Byte()) As Byte() Dim aes As New AesManaged() aes.Key = key aes.IV = iv Dim decryptor As ICryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV) Using cryptoStream As New CryptoStream(inputStream, decryptor, CryptoStreamMode.Read) Using ms As New MemoryStream() cryptoStream.CopyTo(ms) Return ms.ToArray() End Using End Using End Function
然后修改ProcessRequest方法:
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim fileName As String = context.Request.QueryString("filename") If fileName.EndsWith(".encrypted") Then fileName = fileName.Substring(0, fileName.Length - 10) End If Dim aesKey As Byte() = Encoding.UTF8.GetBytes("你的32位密钥") Dim aesIV As Byte() = Encoding.UTF8.GetBytes("你的16位初始化向量") Using inputStream As Stream = context.Request.InputStream Dim originalBytes As Byte() = DecryptStream(inputStream, aesKey, aesIV) Dim savePath As String = Path.Combine("你的服务器存储目录", fileName) File.WriteAllBytes(savePath, originalBytes) End Using End Sub
额外注意点
- 两种方案都需要同步修改客户端和服务器端代码,否则上传的文件是编码/加密后的,无法直接使用。
- 如果Incapsula还会检测文件名,那暂时给文件名加后缀的方式就能避开,服务器端再还原就行。
- Base64编码会让文件体积增加约30%,大文件上传要考虑带宽;加密则不会明显增加体积。
内容的提问来源于stack exchange,提问作者NoName
相关产品推荐
相关产品推荐

