為什麼會講上傳檔案,檢查檔案的副檔名呢(如:jpg、png等)?
在之前,總會看書或上網看教學學習時,會講到檔案上傳,一般都是說檢查檔案的副檔名如:test.jpg,但在一次資訊安全系列的講座上,講解到駭客運用檔案偽裝的手法來騙過程式的檢查,看似一個檔案上傳的動作,卻也是被有心人士利用的一個漏洞,如果上傳一個偽裝的檔案,雖然不執行檔案可能不會有事,但如果讓其他使用者下載,並執行偽裝的檔案(正常的執行word、圖片瀏覽等),那麼就有可能讓其他使用者的電腦被植入木馬等惡意程式。
因此在此分享另外一種利用Byte來檢查檔案副檔名。
參考資料如下:
參考1.建議請先看此篇討論的主題內容,因為也會使用到此篇的寫法 請教判斷是否為真的圖檔的方法
參考2.Validate uploaded image content in ASP.NET
前置作業:
1.請先建立一個aspx網頁,網頁上一個FileUpload、兩個button按鈕
2.在專案中建立一個up_file資料夾,存放上傳的檔案
前端HTML
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload ID="FUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="上傳方法一" />
<asp:Button ID="Button2" runat="server" Text="上傳方法二" />
</div>
</form>
</body>
</html>
後端程式碼
Imports System.IO
Partial Class FileUpload
Inherits System.Web.UI.Page
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
'http://www.dotnetexpertguide.com/2011/05/validate-uploaded-image-content-in.html
'法一
Dim imageHeader As New Dictionary(Of String, Byte())
imageHeader.Add("JPG", New Byte() {&HFF, &HD8, &HFF}) 'C#寫法0xFF, 0xD8, 0xFF;VB.NET必須將0x改為&H
imageHeader.Add("JPEG", New Byte() {&HFF, &HD8, &HFF})
imageHeader.Add("PNG", New Byte() {&H89, &H50, &H4E})
imageHeader.Add("TIF", New Byte() {&H49, &H49, &H2A})
imageHeader.Add("TIFF", New Byte() {&H49, &H49, &H2A})
imageHeader.Add("GIF", New Byte() {&H47, &H49, &H46})
imageHeader.Add("BMP", New Byte() {&H42, &H4D})
imageHeader.Add("ICO", New Byte() {&H0, &H0, &H1})
Dim header() As Byte = Nothing
If FUpload1.HasFile Then
Dim fileExt As String = Nothing
fileExt = FUpload1.FileName.Substring(FUpload1.FileName.LastIndexOf(".") + 1).ToUpper()
Dim filetype As String = Nothing
filetype = fileExt
Dim tmp() As Byte = imageHeader(fileExt)
ReDim Preserve header(tmp.Length - 1)
FUpload1.FileContent.Read(header, 0, header.Length)
If CompareArray(tmp, header) Then
Response.Write("Valid ." & fileExt & " file.")
Try
Dim myFileName As String
myFileName = FUpload1.PostedFile.FileName
Dim c As String = System.IO.Path.GetFileName(myFileName) '取得檔案及副檔名
Dim Uploadfile As String = Server.MapPath("./up_file/") & c
'==========================================
Dim myfilecount As Integer = 2
'檢查檔名是否有重複
While (System.IO.File.Exists(Uploadfile))
c = "img_" & myfilecount '學號_數字
Uploadfile = Server.MapPath("./up_file/") & c & "." & filetype '重新命名並加上副檔名
myfilecount = myfilecount + 1
End While
'==========================================
Dim myImage As System.Drawing.Image = System.Drawing.Image.FromStream(FUpload1.PostedFile.InputStream)
myImage.Save(Uploadfile, ParseImageFormat(filetype))
Catch ex As Exception
Response.Write("sorry,Save error.")
End Try
Else
Response.Write("Invalid ." & fileExt & " file.")
End If
End If
End Sub
'判斷為Byte
Function CompareArray(ByVal a1() As Byte, ByVal a2() As Byte) As Boolean
If a1.Length <> a2.Length Then
Return False
End If
For i As Integer = 0 To a1.Length - 1
If a1(i) <> a2(i) Then
Return False
End If
Next
Return True
End Function
Protected Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click
'法二
If FUpload1.HasFile Then
Dim filetype As String = Nothing
Dim bool_by As Boolean = True
If Me.FUpload1.PostedFile.ContentLength > 0 Then
Dim s As Stream = Me.FUpload1.PostedFile.InputStream
Dim buffer(s.Length - 1) As Byte
s.Read(buffer, 0, s.Length)
Dim header As String = Hex(buffer(0)) & Hex(buffer(1))
Select Case header
Case "FFD8"
My.Response.Write("JPG")
filetype = "jpg"
Case "424D"
My.Response.Write("BMP")
filetype = "bmp"
Case "4749"
My.Response.Write("GIF")
filetype = "gif"
Case "8950"
My.Response.Write("PNG")
filetype = "png"
Case Else
My.Response.Write("Not Supported!" & header)
bool_by = False
End Select
If bool_by = True Then
Try
Dim myFileName As String
myFileName = FUpload1.PostedFile.FileName
Dim c As String = System.IO.Path.GetFileName(myFileName) '取得檔案及副檔名
Dim Uploadfile As String = Server.MapPath("./up_file/") & c
'==========================================
Dim myfilecount As Integer = 2
'檢查檔名是否有重複
While (System.IO.File.Exists(Uploadfile))
c = "img_" & myfilecount '學號_數字
Uploadfile = Server.MapPath("./up_file/") & c & "." & filetype '重新命名並加上副檔名
myfilecount = myfilecount + 1
End While
'==========================================
'重新製作圖檔
Dim myImage As System.Drawing.Image = System.Drawing.Image.FromStream(FUpload1.PostedFile.InputStream)
myImage.Save(Uploadfile, ParseImageFormat(filetype))
Catch ex As Exception
Response.Write("sorry,Save error.")
End Try
End If
s.Close()
s.Dispose() '釋放所有資源要在最後執行,否則即使存檔也無效
Else
bool_by = False
End If
End If
End Sub
Function ParseImageFormat(ByVal type As String) As System.Drawing.Imaging.ImageFormat
Select Case type.ToLower()
Case "jpg"
Return System.Drawing.Imaging.ImageFormat.Jpeg
Case "jpeg"
Return System.Drawing.Imaging.ImageFormat.Jpeg
Case "bmp"
Return System.Drawing.Imaging.ImageFormat.Bmp
Case "gif"
Return System.Drawing.Imaging.ImageFormat.Gif
Case "png"
Return System.Drawing.Imaging.ImageFormat.Png
Case "tiff"
Return System.Drawing.Imaging.ImageFormat.Tiff
Case "wmf"
Return System.Drawing.Imaging.ImageFormat.Wmf
Case "emf"
Return System.Drawing.Imaging.ImageFormat.Emf
Case "icon"
Return System.Drawing.Imaging.ImageFormat.Icon
Case "ico"
Return System.Drawing.Imaging.ImageFormat.Icon
Case "exif"
Return System.Drawing.Imaging.ImageFormat.Exif
Case Else
Return System.Drawing.Imaging.ImageFormat.Jpeg
End Select
End Function
End Class
沒有留言:
張貼留言