
Moodle 5.2.3 - 높음 - 원격 - SQLi - enrol_database가 course idnumber를 SQL에 연결
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-enrol-database-sqli
Moodle LMS 5.2.3 - Moodle
Class: SQLi Reach: Remote
enrol_database::db_get_sql은 여전히 슬래시를 붙이고 문자열을 연결한다. MSA-26-0005 / MDL-88138은 auth_db를 Execute($sql, [$value])로 매개변수화했다. 이 플러그인은 그 형태를 따라 하지 않았다. 설정의 기본값: dbsybasequoting=0, localcoursefield=idnumber. 싱크는 외부 등록 데이터베이스다. Moodle 코어 $DB는 이 경로에 없다.
enrol_database가 활성화된 사이트의 편집 교사가 코스 idnumber를 설정한다. Cron이 이를 보간한다. 외부 등록 DB에서 추가 행이 반환된다.
| ID | 아직 CVE 없음 |
| CWE | CWE-89 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Product | Moodle |
| Affected | 5.2.3 태그 v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116). 플러그인 enrol_database가 켜져 있어야 함. |
| Auth | 편집 교사 (코스 idnumber, 기본 로컬 매핑) |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 전용 |
enrol_database가 활성화된 사이트의 편집 교사가 코스 idnumber를 설정하여 외부 등록 데이터베이스에 SQL을 주입한다. 그런 다음 Cron sync_enrolments가 해당 SQL을 실행한다.
| 권한 | 메서드 / 싱크 | 정찰 / 무결성 / 가용성 | 실험실 입증 또는 추론 |
|---|---|---|---|
| 외부 등록 SELECT에 SQL 조각 삽입 | Cron sync_enrolments -> db_get_sql($table, array($coursefield=>$course->mapping), ...) -> $extdb->Execute($sql) | 쿼리 문자열의 무결성 | 실험실 입증. 연결된 SQL은 WHERE courseid = 'LABCOURSE\'' OR 1=1 -- ' |
| 해당 외부 DB에서 다른 코스의 등록 행 읽기 | 문자열이 닫힌 후 동일한 SELECT | 정찰 | 실험실 입증. 정상: 1행 teacher-local. 주입: MOODLE-ENROL-DATABASE-SQLI-WITNESS를 포함한 2행 |
| 플러그인이 꺼져 있을 때 쿼리 건너뛰기 | 동일한 가젯, plugin=off | n/a | 실험실 입증 차단됨. executed=false, 빈 SQL, 0행 |
| 동일한 페이로드를 바인드 매개변수로 유지 | MSA-26-0005의 auth_db 잔재: Execute($sql, [$value]) | n/a | 실험실 입증 차단됨. style=param은 0행을 반환했고 SQL에 ?가 포함됨 |
| 추가 행에 명시된 Moodle 사용자 등록/등록 취소/역할 할당 | Cron이 requestedenrols를 적용한 후 | 등록의 무결성 | 추론. 실험실은 등록 DB의 추가 행에서 멈춤 |
| 등록 DB 사용자로서 FILE / INTO OUTFILE | 해당 계정에 FILE 권한이 있는 경우 동일한 싱크 | 해당 DB 호스트의 무결성 / 가용성 | 추론. 입증되지 않음. OS LPE 아님 |
| 학생 제어 경로 | 관리자가 localuserfield=email(또는 유사)을 매핑한 경우에만 | n/a | 추론. 기본 경로는 교사 idnumber |
이 잔재에서 차단됨: Moodle 코어 $DB; 플러그인 비활성화(쿼리 없음); 인증되지 않은 접근; OS 셸; 스택 쿼리(이 mysqli 가젯은 단일 문장). enrol_database가 없는 기본 Moodle은 이 버그가 아니다.
동일 핀 잔재: Blackboard img 파일 읽기, grades feedback IDOR, 숨겨진 성적 항목.
MSA-26-0042/0043 이후 moodle/moodle v5.2.3을 핀했다. MSA-26-0005는 플레이스홀더로 auth_db를 차단했다. 동일한 종류의 외부 DB와 통신하고 여전히 db_addslashes를 가지고 있기 때문에 enrol_database를 열었다.
dbsybasequoting은 기본값이 0이므로 '만 두 배로 늘어난다. idnumber의 백슬래시-따옴표가 MySQL 문자열을 닫는다.
이미 기록된 잘못된 방향: Moodle 코어 $DB를 싱크로 취급(그렇지 않음); FILE이 MySQL 권한으로 존재한다는 이유로 OS LPE라고 부름(입증되지 않음, 이 잔재가 아님); 학생 이메일을 기본 매핑으로 가정(관리자가 localuserfield를 변경해야 함). 리버스 셸. 연극.
핀 빌더들의 충실한 가젯이며, 전체 Moodle PHP 앱이 아니다. php:8.3-cli가 복사된 db_get_sql / db_addslashes / db_encode를 제공한다. mysql:8.0이 두 개의 등록 행을 보유한다.
python3 moodle-enrol-database-sqli-Abraxas-Labs.py
또는
cd lab
./run.sh
오직 http://127.0.0.1:19570만 대상으로 한다. Compose 프로젝트 moodle-enrol-database-sqli. 실행 후 스택은 해체된다.
SUCCESS moodle-enrol-database-sqli how=gadget plugin-off=no-query clean-rows=1 inject-rows=2 sql-concat=yes param-rows=0 extra=yes sink=enrol-db MOODLE-ENROL-DATABASE-SQLI-WITNESS
auth_db의 매개변수화된 쿼리를 복사한다(MDL-88138). 매핑된 코스 / 사용자 값을 Execute($sql, [$value])로 전달한다. db_addslashes를 '$value'에 연결하지 않는다. 코스 idnumber의 따옴표가 다른 코스의 행을 반환하지 않는다는 테스트를 추가한다.
lib.php (db_get_sql, db_addslashes, sync_enrolments)auth_dbGNU Affero GPL v3.0. LICENSE 참조. 루프백 실험실 전용. 보증 없음.