NoSQL Injection 문제입니다. Admin 권한을 탈취하는 것이 아닌 hidden user를 찾는 것이 목표입니다.
그전에 앞서 우선 NoSQL 대해 알아보도록 하겠습니다.
NoSQL 이란?
NoSQL(=Not Only SQL)은 문서 저장소, 키값 저장소, 그래프 등과 같은 다른 저장 메커니즘에 의존하는 비관계형 데이터베이스입니다. 기존에 사용하던 관계형 데이터베이스로는 엄청난 수의 서버에 데이터를 배포해야 하는 소셜 네트워크 서비스를 제공할 수 없었기에 더 융통성 있고, 데이터의 저장 및 검색에 특화된 메커니즘, NoSQL이 각광받게 되었습니다.
가장 많이 쓰는 NoSQL DBMS로는 MongoDB, Cassandra, Redis 등이 있으며, NoSQL 데이터베이스의 인기는 지속적으로 증가하고 있는 추세입니다.
NoSQL 또한 초창기에는 보안적으로 미흡한 부분이 많이 보여지고 있습니다. 암호화, 인증 및 역할 관리 미흡, 네트워크 노출, DOS 공격 등을 허용하고 있었습니다. 그중에서 가장 자주 사용되는 공격 기법인 NoSQL Injection에 대해 써보려고 합니다.
NoSQL Injection
NoSQL Injection은 SQL Injection 공격과 크게 다르지 않습니다. 문법의 차이일 뿐입니다.
사용자 id와 패스워드를 이용한 로그인 매커니즘을 예를 들어보겠습니다. 아래는 HTTP POST 페이로드입니다.
userid=zzzz0&passwd=password1!
그리고 이것을 처리하고 MongoDB 쿼리 하는 PHP 코드는 아래와 같습니다.
db->logins->find(array("userid"=>$_POST["userid"], "passwd"=>$_POST["passwd"]));
개발자가 전송하는 쿼리는 다음과 같습니다.
db.logins.find({ userid : 'zzzz0', passwd : 'password1!' })
PHP는 공격자가 악의적인 페이로드를 보낼 수 있도록 연관 배열 메커니즘을 제공하고 있습니다.
userid[$ne]=1&passwd[$ne]=1
위와 같은 페이로드가 왔을 때, PHP 코드는 아래와 같습니다.
array("userid"=> array("$ne" => 1), "passwd" => array("$ne" => 1));
MongDB 쿼리는 다음과 같습니다.
db.logins.find({ userid : { $ne: 1 }, passwd : { $ne: 1 } })
$ne는 != 를 의미하는데, 이는 userid가 1이 아니고, passwd가 1이 아닌 항목, 즉 로그인 컬렉션의 모든 항목(사용자)을 반환한다는 것을 의미합니다. 따라서, 이 취약점을 이용해 로그인 인증 메커니즘을 우회해 로그인, 비인가 데이터 액세스, 비인가자 서비스 이용 등의 공격이 이루어질 수 있습니다.
문제를 풀어보면서 NoSQL Injection을 더 이해해보도록 하겠습니다.
문제에 들어가면, Nickname과 패스워드를 입력받는 로그인 폼이 보입니다.
어떤 방식으로 로그인이 이루어지는지 확인해보기 위해 admin/admin을 입력해보았습니다.
GET 메소드를 이용해 login, pass 파라미터가 전송되고 있습니다.
위에서 입력한 admin/admin의 결과 값은 Bad username or bad password!라고 로그인 에러가 출력됩니다.
앞에서 확인한 방법으로 $ne를 이용해 로그인 메커니즘 우회를 시도해보았습니다.
login이 admin 아니고, pass가 admin(임의 사용)이 아닌 사용자, test로 로그인되었습니다.
이번에는 login이 test가 아니고, pass가 admin이 아닌 사용자로 연결을 시도해보았습니다.
문제의 목표인 hidden user가 나오지 않고 그냥 admin으로 로그인되어버립니다.
MongoDB는 $ne 뿐만 아니라 많은 쿼리 연산자를 제공하고 있습니다.
{}[]() | 관계 묶음 | $ne | not equal | $regex | 정규 표현식 | ||
', " | 문자열 처리 | $exist | 키 존재 여부 | $gt | > | ||
: | 연결자 | $where | 필터링 스크립트 | $lt | < |
MongoDB에서는 정규 표현식을 사용할 수 있었습니다.
따라서, login이 admin도 아니고 test도 아닌 사용자를 찾는 쿼리를 전송하니 hidden user가 출력되었습니다.
정규 표현식을 잘 설명한 블로그 링크를 첨부하도록 하겠습니다.
https://hamait.tistory.com/342
※ NoSQL 참고 자료
-https://medium.com/@shukla.iitm/nosql-injection-8732c2140576
-https://www.samsungsds.com/global/ko/support/insights/1195843_2284.html
'Study > Wargame' 카테고리의 다른 글
[root-me] JSON Web Token (JWT) - Weak secret (0) | 2020.03.06 |
---|---|
[root-me] JSON Web Token(JWT) - Public key (0) | 2020.03.05 |
[root-me] File upload - ZIP (0) | 2020.02.12 |
[root-me] PHP - preg_replace() (0) | 2020.01.08 |
[root-me] LDAP injection - Authentication (0) | 2020.01.08 |