今天接續昨天最後提到的acces token跟refresh token,直接進入第7步的練習吧!在這一題中,我們需要以昨天提到的access token及refresh token等概念,讓Tom來幫你結這單。
另外,建議搭配程式碼做參考來解,而程式碼內容可以在WebGoat的github中找到(網址:https://github.com/WebGoat/WebGoat/blob/develop/webgoat-lessons/jwt/src/main/java/org/owasp/webgoat/plugin/JWTRefreshEndpoint.java )。
題目中提到我們可以參考之前外洩的一份log資料,而從這份log資料中我們可以發現一串JWT,以及幾個頁面功能,疑似為結帳、登入、新增物品等功能。
把這串JWT解碼後,發現這串JWT是Tom所有的token。
那我們就先用ZAP攔截按下Checkout按鈕後的HTTP請求是長什麼樣子吧。
如果不做任何事情就把這個請求送出的話,伺服器會回傳一個錯誤,並告訴我們的HTTP Header裡少了Authorization這個參數及其值。
從github的程式碼中我們可以看出Authorization這個參數的值其實就是要放JWT。
接著來試試看把剛剛從外洩資料裡看到的JWT當成值送出看看。
結果發現還是收到了錯誤訊息,說明這個token已經過期了,但至少這個訊息讓我們知道這個參數的確是要放JWT,也就是access token的地方。
那接下來我們只要想辦法拿到重新整理過後的Tom的新access token,就能解開這關了。
首先,我們從程式碼中發現一個寫死的帳號密碼,也就是「Jerry」這個帳號的密碼是「bm5nhSkxCXZkKRy4」,另外我們也發現這段程式是接收json格式的參數,且這個josn有兩個參數,分別是「user」跟「password」。
同時,我們發現login這個功能可以幫使用者建立一組新的token,所以我們就決定先用ZAP攔截一個結帳的封包,並把它的內容改為Jerry要登入,以取得一組access token跟refresh token,注意記得要把Header中的Content-Type值改為「application/json」,不然會導致伺服器錯誤。
送出後,伺服器回傳一組access token跟refresh token給我們,接著就可以利用這個refresh token去幫Tom換到有效的access token啦。
從程式碼可以看出,如果要用refresh token向伺服器申請到新的access token的話就要用newToken這個功能,而這個功能會接收兩個值,一個是HTTP Header中的Authorization參數要放一個過期的access token,而另外也要用json格式提供refresh token。此外,程式碼也看的出來系統並不會去驗證refresh token的所有者是誰,只會看他是不是一個有效的token,所以我們就可以利用這點,用Jerry的refresh token去幫Tom申請新的access token。
所以我們再次用ZAP攔截一個結帳的封包,並把它的內容改為Tom要用newToken的功能,用Jerry剛剛拿到的refresh token去申請Tom的新access token,另外這邊記得也要把Header中的Content-Type值改為「application/json」,不然會導致伺服器錯誤。。
送出後發現伺服器回傳了一組新的token給我們。
拿去驗證一下發現真的是屬於Tom的token沒錯。
好啦,既然拿到Tom的access token了,我們就可以結帳啦。我們再次用ZAP攔截一個結帳的封包,並把Authorization這個參數及其值(Tom的新access token)HTTP Header後送出。
然後就成功讓Tom付錢了!可喜可賀!
完成了第7步的練習,第8步的練習先留給大家自行挑戰吧,等我挑戰完也會再分享給大家的!