A biztonság jó dolog.

Csak épp néha piszokul bosszantó.

Vegyük elő kedvenc Outlookunkat és tapasztalni fogjuk, hogy a beérkezett levelek egy jó részében nincsenek képek, csak egy kék figyelmeztető sáv, hogy ha akarjuk, akkor letölthetjük a képeket, de ez biztonságilag kockázatos.

Miért van ez így? Miért van az, hogy bizonyos levelekben vannak képek és bizonyos levelekben nincsenek?

A HTML formátumú levelekbe a képeket két módszer szerint tudjuk berakni.

Az egyik az úgy nevezett Online HTML. Ebben az esetben a levélben van egy img tag, aminek az src attributuma egy web szerveren tárolt képre mutat. Ennek a megoldásnak az az előnye, hogy az elküldött levél maga viszonylag kicsi lesz, mert a képek nincsenek benne. További előny, hogy a küldő tud a háttérben statisztikát vezetni arról, hogy az adott levelet megnyitották-e (ha letöltötte a címzett a képet, akkor megnyitotta a levelet). Előny lehet még a feladó számára, hogy a képet utólag is tudja módosítani*. Ennek a megoldásnak vannak hátrányai is. Az Outlook az ilyen levelekre rakja fel a fent említett kék csíkot és nem tölti le a képeket. Ha valamiért a címzett, vagy a küldő web szervere offline, akkor nem tudunk hozzáférni a képekhez.

A másik az Offline HTML, amelyben az img tag src attributuma egy cid bejegyzést tartalmaz ami a levélben magában lévő rejtett csatolmányra mutat. Ez tartalmazza a képet magát. Előnye, hogy mindig elérhető a címzett számára, az Outlook nem szűri ki, ugyanakkor hátránya, hogy nagyméretűek lesznek a levelek tőle.

Vajon az Outlook miért szűri ki az első levél típusban szereplő képeket?

Mert ez a gépre nézve potenciális támadást is hordozhat. Az elmúlt években több olyan sérülékenység is napvilágra került, amit a Windows képfeldolgozó motorjában találtak és speciálisan formázott képfájlal kihasználhatóak voltak. Tehát, ha nem töltöm le a képet, akkor nem tud kárt okozni.

De engem zavar, hogy állandóan kézzel kell letöltenem a levelet. Ki lehet kapcsolni?

Igen, de nem érdemes, az ok az előbb taglalt biztonság.

Jó, de akkor mi a megoldás? Hogyan lehetne elérni, hogy azoknál a leveleknél, amiknél én szeretném automatikusan letöltődjenek a képek (pl. rendszeres, olvasott hírlevelek).

Erre van megoldás. Ha megnézzük az Outlook biztonsági beállításai között találunk egy ilyet:

 Trusted Zone

Bekarikáztam a lényeget. Tehát, ha a kép forrását berakjuk az Internet Explorer Trusted Zone-ba akkor a képet automatikusan le tudjuk tölteni.

Ok. Akkor rakjuk be. Na, ezzel lesz némi gond. Nincs olyan gomb, menü, valami az Outlookban, ami ezt megtenné nekünk. Ha van egy levelünk, aminek a linkjeit használni szeretnék, akkor szükségünk lenne a levél HTML forrására, hogy ki tudjuk másolni a megfelelő linket. Sajnos ezzel sem rendelkezünk, ugyanis ezt az  Outlook eldugja előlünk.

Mit tehetünk? Programozunk.

Írtam egy pici Outlook makrót, ami beköltözik a levél context menüjébe és ha ott rábökünk a Trust Picture Source menüpontra, akkor a levélben (vagy levelekben) lévő img src attributumokból kibogarássza a web oldalak címeit és berakja őket a Trusted Zone-ba.

A dolog működik, csak egyetlen szépséghibája van. A működés eredménye, csak az Outlook újraindítása után látható. A kód Outlook 2007-en működik (a korábbiakon nem).

Akkor rakjuk fel!

Nyissunk az Outlookban egy VBA ablakot (Alt+F11) A ThisOutlookSession-on jobb egérgomb, View Code.

Ide másoljuk be ezt:

Option Explicit
Private TrustPictureContextMenus As TrustPicturesMenu
Private WithEvents objOL As Outlook.Application
Private Sub Application_Quit()
    Set TrustPictureContextMenus = Nothing
End Sub
Private Sub Application_Startup()
    Set TrustPictureContextMenus = New TrustPicturesMenu
End Sub

Ezek után a Class Modules ágon jobb egérgomb, Insert/Class Module. Majd a keletkezett modult nevezzük át TrustPicturesMenu-re.

A kód ablakba pedig rakjuk be ezt:

Option Explicit
Private WithEvents objOL As Outlook.Application
Private WithEvents objTrustPictureButton As Office.CommandBarButton
Private Sub Class_Initialize()
    Set objOL = Outlook.Application
End Sub
Private Sub objTrustPictureButton_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
    Dim RE As Object, REMatches As Object
    Set RE = CreateObject("vbscript.regexp")
    With RE
        .MultiLine = False
        .Global = True
        .IgnoreCase = True
        .Pattern = "<img\b[^>]*src=""(https?)://([^/]*)[^""]*""[^>]*>"
    End With
    ReDim Sites(1, 0) As String
    Dim objItem
    Dim SiteFound As String
    Dim ProtocolFound As String
    Dim SiteInArr As Boolean
    Dim SiteMatch
    Dim Site
    Dim i
    For Each objItem In objOL.ActiveExplorer.Selection
        Set REMatches = RE.Execute(objItem.HTMLBody)
        For Each SiteMatch In REMatches
            SiteFound = LCase(SiteMatch.SubMatches(1))
            ProtocolFound = LCase(SiteMatch.SubMatches(0))
            SiteInArr = False
            For i = 0 To UBound(Sites, 2)
                If Sites(0, i) = SiteFound And Sites(1, i) = ProtocolFound Then
                    SiteInArr = True
                    Exit For
                End If
            Next
            If Not SiteInArr Then
                If Sites(0, UBound(Sites, 2)) <> "" Then
                    ReDim Preserve Sites(1, UBound(Sites, 2) + 1)
                End If
                Sites(0, UBound(Sites, 2)) = SiteFound
                Sites(1, UBound(Sites, 2)) = ProtocolFound
            End If
        Next
    Next
    Dim DomainPartArr
    Dim HostPart As String
    Dim DomainPart As String
    Dim j, k
    For i = 0 To UBound(Sites, 2)
        DomainPartArr = Split(Sites(0, i), ".")
        DomainPart = ""
        HostPart = ""
        For j = 0 To UBound(DomainPartArr) - 2
            HostPart = HostPart + DomainPartArr(j)
            If j < UBound(DomainPartArr) - 2 Then
                HostPart = HostPart + "."
            End If
        Next
        For k = j To UBound(DomainPartArr)
            DomainPart = DomainPart + DomainPartArr(k)
            If k < UBound(DomainPartArr) Then
                DomainPart = DomainPart + "."
            End If
        Next
        RegKeySave "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\" _
                    & DomainPart & "\" & HostPart & "\" & Sites(1, i), 2, "REG_DWORD"
    Next
End Sub
Sub RegKeySave(i_RegKey As String, i_Value, Optional i_Type As String = "REG_SZ")
    Dim myWS As Object
    Set myWS = CreateObject("WScript.Shell")
    myWS.RegWrite i_RegKey, i_Value, i_Type
End Sub
Private Sub objOL_ItemContextMenuDisplay(ByVal CommandBar As Office.CommandBar, ByVal Selection As Selection)
    Dim objItem As Object
    Dim blnFoundItem  As Boolean
    Dim objCBB As Office.CommandBarButton
    For Each objItem In Selection
        If objItem.Class = olMail Or objItem.Class = olPost Then
            blnFoundItem = True
            Exit For
        End If
    Next
    If blnFoundItem = True Then
        Set objCBB = CommandBar.Controls.Item(1)
        objCBB.BeginGroup = True
        Set objCBB = CommandBar.Controls.Add(msoControlButton, , , , True)
        objCBB.Style = msoButtonWrapCaption
        objCBB.Caption = "Trust Picture Source"
        objCBB.BeginGroup = True
        Set objTrustPictureButton = objCBB
    End If
End Sub

 Mentsük el az egészet.

Ezek után, már csak a kód biztonsági beállításokat kell megtennünk, hogy a dolog működjön (digitális aláírás, miegymás 🙂 )

Használata:

Odanavigálunk kiszemelt levelünkhöz, nyomunk rajta egy jobb egérgomot és…

Context Menu

 * Erről van egy történetem. Van egy ismerősöm, aki az egyik magyar banknál dolgozott biztonsági szakértőként. Egy spammer banda az ő bankjuk nevében küldött megtévesztő leveleket (phishing). A rosszfiúk elkövették azt a hibát, hogy Online HTML levelet küldtek, amiben a logo a bank honlapjára mutatott. Az ismerősöm fogta magát és kicserélte a logót a honlapon egy figyelmezetésre, melyben jelezte, hogy a levél hamis és a tartalmát senki se vegye figyelembe.