Jak zapobiec przekierowaniu przez ramkę IFRAME okna najwyższego poziomu


135

Niektóre strony internetowe mają kod do „wyłamywania” IFRAMEzałączników, co oznacza, że ​​jeśli strona Ajest ładowana jako IFRAMEstrona nadrzędna, Pczęść JavaScript Aprzekierowuje do zewnętrznego okna A.

Zwykle ten JavaScript wygląda mniej więcej tak:

<script type="text/javascript">
  if (top.location.href != self.location.href)
     top.location.href = self.location.href;
</script>

Moje pytanie brzmi: jako autor strony nadrzędnej Pi nie będący autorem strony wewnętrznej A, jak mogę zapobiec Atemu wybuchowi?

PS Wydaje mi się, że powinno to być naruszenie bezpieczeństwa w różnych witrynach, ale tak nie jest.


Myślę, że nie możesz wiele zrobić ... jeśli nie jesteś autorem zawartości ramki.
scunliffe

Odpowiedzi:


43

Spróbuj użyć właściwości onbeforeunload, która pozwoli użytkownikowi zdecydować, czy chce opuścić stronę.

Przykład: https://developer.mozilla.org/en-US/docs/Web/API/Window.onbeforeunload

W HTML5 możesz użyć właściwości piaskownicy. Zobacz odpowiedź Pankrata poniżej. http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/


1
iFrames zrobić umożliwienia komunikacji między domenami, choć przy użyciu postMessage. To nie jest zagrożenie dla bezpieczeństwa, ale ktoś może chcieć wiedzieć, że taka możliwość istnieje, gdy zobaczy Twój komentarz. :)
coreyward

W chwili pisania tej odpowiedzi nie było to możliwe. Dziękuję za zwrócenie uwagi.
fasih.rana

@SirDarius, czy mógłbyś pokazać przykład, bardzo ceniony.
user198989

Użytkownik nie będzie wiedział, dlaczego pojawia się to potwierdzenie i prawdopodobnie wybierze losową odpowiedź. Nie polecam go używać. Istnieją inne rozwiązania - plik sandbox.
oriadam

1
@ fasih.rana Drugi artykuł bardzo mi pomógł. Dziękuję;)
MrD

127

W HTML5 dodano atrybut piaskownicy iframe . W chwili pisania tego tekstu działa to w Chrome, Safari, Firefox i najnowszych wersjach IE i Opery, ale robi prawie to, co chcesz:

<iframe src="url" sandbox="allow-forms allow-scripts"></iframe>

Jeśli chcesz zezwolić na przekierowania najwyższego poziomu, określ sandbox="allow-top-navigation".


czekaj, co? Pozwolili ci to zrobić? Pomyślałem, że jeśli witryna chce się wydostać, wszystkie przeglądarki na to pozwolą. Jak ludzie powinni trzymać swoją witrynę z dala od ramek iframe, gdy jest to wokół? Nie narzekam, super.
Farzher


1
@StephenSarcsamKamenar Jeśli chcesz chronić swoją witrynę przed wyświetlaniem w ramce iframe, dostępny jest nagłówek X-Frame-Options z wartością SAMEORIGIN . Większość nowoczesnych przeglądarek nie wyświetla witryny w ramce iframe z tym nagłówkiem.
Grzegorz

4
Niestety sandboxnie zezwala na Flash ani żaden inny typ obiektu w ramce w trybie piaskownicy, przez co ta sandboxfunkcja jest w wielu przypadkach bezużyteczna.
oriadam

1
Witryny nie powinny „wybuchać”, by zaprotestować przeciwko umieszczeniu ich w elemencie iframe. Mogą po prostu pokazać wiadomość lub zniknąć. Niestety, zezwolenie na uruchamianie skryptów w elemencie iframe nadal otwiera cię na nieuczciwy element iframe wykonujący while (1) {} i inne nieskończone pętle. Chciałbym, aby każdy element iframe mógł uzyskać własny wątek.
Gregory Magarshak

51

Używam piaskownicy = „...”

  • allow-formularze umożliwia przesłanie formularza
  • allow-popups zezwala na wyskakujące okienka
  • allow-pointer-lock umożliwia blokowanie wskaźnika
  • allow-same-origin pozwala dokumentowi zachować swoje pochodzenie
  • allow-scripts umożliwia wykonywanie JavaScript, a także umożliwia automatyczne uruchamianie funkcji
  • Zezwól na nawigację od góry umożliwia wyjście dokumentu z ramki przez nawigację w oknie najwyższego poziomu

Górna nawigacja jest tym, co chcesz zapobiec, więc pomiń to, a nie będzie to dozwolone. Wszystko, co zostanie pominięte, zostanie zablokowane

dawny.

        <iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src="http://www.example.com"</iframe>

3
Pamiętaj, że Flash (i wszystkie inne obiekty) również zostaną zablokowane, bez możliwości zezwolenia na to. Ta „funkcja bezpieczeństwa” uniemożliwia mi jednoczesne korzystanie z piaskownicy
oriadam


5

Wiem, że minęło dużo czasu, odkąd pytanie zostało zrobione, ale tutaj moja ulepszona wersja będzie czekała 500 ms na każde kolejne połączenie tylko wtedy, gdy ramka iframe jest załadowana.

<script type="text/javasript">
var prevent_bust = false ;
    var from_loading_204 = false;
    var frame_loading = false;
    var prevent_bust_timer = 0;
    var  primer = true;
    window.onbeforeunload = function(event) {
        prevent_bust = !from_loading_204 && frame_loading;
        if(from_loading_204)from_loading_204 = false;
        if(prevent_bust){
            prevent_bust_timer=500;
        }
    }
    function frameLoad(){
        if(!primer){
            from_loading_204 = true;
            window.top.location = '/?204';
            prevent_bust = false;
            frame_loading = true;
            prevent_bust_timer=1000;
        }else{
            primer = false;
        }
    }
    setInterval(function() {  
        if (prevent_bust_timer>0) {  
            if(prevent_bust){
                from_loading_204 = true;
                window.top.location = '/?204';
                prevent_bust = false;
            }else if(prevent_bust_timer == 1){
                frame_loading = false;
                prevent_bust = false;
                from_loading_204 = false;
                prevent_bust_timer == 0;
            }



        }
        prevent_bust_timer--;
        if(prevent_bust_timer==-100) {
            prevent_bust_timer = 0;
        }
    }, 1);
</script>

i onload="frameLoad()"i onreadystatechange="frameLoad();"mogą być dodawane do ramy lub iframe.



2

Ponieważ strona, którą ładujesz wewnątrz elementu iframe, może wykonać kod „wyłamać” za pomocą parametru setInterval, onbeforeunload może nie być tak praktyczne, ponieważ może spowodować wyświetlenie użytkownikowi komunikatu „Czy na pewno chcesz wyjść?” okna dialogowe.

Istnieje również atrybut bezpieczeństwa iframe, który działa tylko w IE i Opera

:(


2

W moim przypadku chcę, aby użytkownik odwiedził wewnętrzną stronę, aby serwer widział jego adres IP jako odwiedzający. Jeśli użyję techniki proxy php, myślę, że strona wewnętrzna zobaczy mój adres IP serwera jako odwiedzającego, więc nie jest to dobre. Jedynym rozwiązaniem, jakie do tej pory otrzymałem, jest chęć włączenia się przed załadowaniem. Umieść to na swojej stronie:

<script type="text/javascript">
    window.onbeforeunload = function () {                       
         return "This will end your session";
    }
</script>

Działa to zarówno w Firefoksie, jak i to jest to, co testowałem. znajdziesz wersje używające czegoś takiego jak evt.return (cokolwiek) bzdury ... to nie działa w Firefoksie.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.