General: Better validation for iframe event origins (#6856)
This commit is contained in:
parent
889d07823d
commit
7e789e6e77
@ -1,12 +1,13 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type React from '../../lib/teact/teact';
|
||||
import { memo, useCallback, useEffect } from '../../lib/teact/teact';
|
||||
import { memo, useCallback, useEffect, useRef } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { TabState } from '../../global/types';
|
||||
|
||||
import { getCanPostInChat } from '../../global/helpers';
|
||||
import { selectChat, selectChatFullInfo } from '../../global/selectors';
|
||||
import { isMessageFromIframe } from '../../util/browser/iframe';
|
||||
|
||||
import useInterval from '../../hooks/schedulers/useInterval';
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
@ -34,6 +35,7 @@ const GameModal: FC<OwnProps & StateProps> = ({ openedGame, gameTitle, canPost }
|
||||
const lang = useOldLang();
|
||||
const { url, chatId, messageId } = openedGame || {};
|
||||
const isOpen = Boolean(url);
|
||||
const frameRef = useRef<HTMLIFrameElement>();
|
||||
|
||||
const sendMessageAction = useSendMessageAction(chatId);
|
||||
useInterval(() => {
|
||||
@ -41,7 +43,10 @@ const GameModal: FC<OwnProps & StateProps> = ({ openedGame, gameTitle, canPost }
|
||||
}, isOpen && canPost ? PLAY_GAME_ACTION_INTERVAL : undefined);
|
||||
|
||||
const handleMessage = useCallback((event: MessageEvent<string>) => {
|
||||
if (!chatId || !messageId) return;
|
||||
if (!chatId || !messageId || !isMessageFromIframe(event, frameRef.current)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.data) as GameEvents;
|
||||
if (data.eventType === 'share_score') {
|
||||
@ -77,6 +82,7 @@ const GameModal: FC<OwnProps & StateProps> = ({ openedGame, gameTitle, canPost }
|
||||
>
|
||||
{isOpen && (
|
||||
<iframe
|
||||
ref={frameRef}
|
||||
className="game-frame"
|
||||
onLoad={handleLoad}
|
||||
src={url}
|
||||
|
||||
@ -6,6 +6,7 @@ import type { WebApp, WebAppInboundEvent, WebAppOutboundEvent } from '../../../.
|
||||
|
||||
import { VERIFY_AGE_MIN_DEFAULT } from '../../../../config';
|
||||
import { getWebAppKey } from '../../../../global/helpers';
|
||||
import { isMessageFromIframe } from '../../../../util/browser/iframe';
|
||||
import { extractCurrentThemeParams } from '../../../../util/themeStyle';
|
||||
import { REM } from '../../../common/helpers/mediaDimensions';
|
||||
|
||||
@ -172,10 +173,8 @@ const useWebAppFrame = (
|
||||
if (ignoreEventsRef.current) {
|
||||
return;
|
||||
}
|
||||
const contentWindow = ref.current?.contentWindow;
|
||||
const sourceWindow = event.source as Window;
|
||||
|
||||
if (contentWindow !== sourceWindow) {
|
||||
if (!isMessageFromIframe(event, ref.current)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import { memo, useCallback, useEffect } from '../../lib/teact/teact';
|
||||
import { memo, useCallback, useEffect, useRef } from '../../lib/teact/teact';
|
||||
import { getActions } from '../../global';
|
||||
|
||||
import { TME_LINK_PREFIX } from '../../config';
|
||||
import { isMessageFromIframe } from '../../util/browser/iframe';
|
||||
|
||||
import useOldLang from '../../hooks/useOldLang';
|
||||
|
||||
@ -35,14 +35,19 @@ interface WebAppOpenTgLinkEvent {
|
||||
|
||||
type IframeCallbackEvent = PaymentFormSubmitEvent | WebAppOpenTgLinkEvent;
|
||||
|
||||
const ConfirmPayment: FC<OwnProps> = ({
|
||||
const ConfirmPayment = ({
|
||||
url, noRedirect, onClose, onPaymentFormSubmit,
|
||||
}) => {
|
||||
}: OwnProps) => {
|
||||
const { openTelegramLink } = getActions();
|
||||
|
||||
const lang = useOldLang();
|
||||
const frameRef = useRef<HTMLIFrameElement>();
|
||||
|
||||
const handleMessage = useCallback((event: MessageEvent<string>) => {
|
||||
if (!isMessageFromIframe(event, frameRef.current)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(event.data) as IframeCallbackEvent;
|
||||
const { eventType, eventData } = data;
|
||||
@ -76,6 +81,7 @@ const ConfirmPayment: FC<OwnProps> = ({
|
||||
return (
|
||||
<div className="ConfirmPayment">
|
||||
<iframe
|
||||
ref={frameRef}
|
||||
src={url}
|
||||
title={lang('Checkout.WebConfirmation.Title')}
|
||||
allow="payment"
|
||||
|
||||
3
src/util/browser/iframe.ts
Normal file
3
src/util/browser/iframe.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function isMessageFromIframe(event: MessageEvent, iframe?: HTMLIFrameElement) {
|
||||
return Boolean(iframe?.contentWindow && event.source === iframe.contentWindow);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user