sqlmap은 SQL 주입 감지의 아티팩트라고 할 수 있지만 sqlmap을 사용하여 SQL 주입을 테스트하는 효율성은 매우 낮습니다. 각 URL을 수동으로 테스트해야 합니다. sqlmap 개발자는 인터페이스 호출을 통해 직접 작동할 수 있는 sqlmapapi.py를 추가하여 sqlmap 명령 실행을 단순화했습니다.
sqlmap api는 서버와 클라이언트로 구분됩니다. sqlmap api에는 두 가지 모드가 있습니다. 하나는 HTTP 프로토콜 기반 인터페이스 모드이고, 다른 하나는 명령줄 기반 인터페이스 모드입니다.
sqlmap 소스코드 다운로드 주소: https://github.com/sqlmapproject/sqlmap/
python sqlmapapi.py -h
명령이 성공하면 명령줄에 일부 정보가 반환됩니다. 다음 명령은 대략적으로 api 서버가 로컬 포트 8775에서 실행되고 admin 토큰이 c6bbb0c1f86b7d7bc2ed6ce3e3bbdcb5 등이라는 의미입니다.
하지만 위의 방법으로 api 서버를 열면 서버와 클라이언트가 동시에 열릴 때 단점이 있습니다. 동일한 호스트가 아니면 연결이 불가능하므로 이 문제를 해결하려면 python sqlmapapi.py -s -H "0.0.0.0" -p 명령을 입력하여 api 서버를 열 수 있습니다. 8775 명령이 성공한 후 원격 클라이언트가 API 서버에 연결할 원격 호스트 IP와 포트를 지정합니다.3. 명령줄 기반 인터페이스 모드
3.1. 클라이언트를 열고 주입 명령을 시작합니다
python sqlmapapi.py -c클라이언트와 서버가 동일한 컴퓨터가 아닌 경우 다음 명령을 입력합니다. QPython SQLMAPAPI.PY -C -H "192.168.1.101" -P 87753.2, 도움말 명령, 모든 명령 가져오기
R
help 显示帮助信息 new ARGS 开启一个新的扫描任务 use TASKID 切换 taskid data 获取当前任务返回的数据 log 获取当前任务的扫描日志 status 获取当前任务的扫描状态 option OPTION 获取当前任务的选项 options 获取当前任务的所有配置信息 stop 停止当前任务 kill 杀死当前任务 list 显示所有任务列表 flush 清空所有任务 exit 退出客户端
3.3, 테스트 주입3.3.1.new 명령
예: new -u "http://www.baidu.com"
-u 매개변수만 지정했지만 반환된 정보를 보면 새 명령을 입력한 후, /task/new는 먼저 새 taskid를 생성하도록 요청한 다음 작업을 시작하기 위한 요청을 시작하므로 이 모드는 기본적으로 HTTP 프로토콜을 기반으로 함을 알 수 있습니다.3.3.2. 상태 명령
은 작업의 스캔 상태를 가져옵니다. 반환된 콘텐츠의 상태 필드가 종료되면 스캔이 완료되었음을 의미합니다. 실행 중이면 검사가 아직 진행 중이라는 의미입니다. 아래 그림은 스캔이 완료된 스크린샷입니다:
3.3.3.data 명령
반환된 데이터의 데이터 필드가 비어 있지 않으면 주입이 성공한 것으로 결론을 내릴 수 있습니다. 이 예에서는 데이터베이스 유형, 페이로드, 주입 매개변수와 같은 정보가 포함된 SQL 주입이 포함된 반환 콘텐츠를 보여줍니다.
4. HTTP 프로토콜 기반 인터페이스 모드
sqlmapapi.py의 http 인터페이스 호출 모드를 기반으로 하는 h의 주요 기능을 간략하게 소개하면 lib/utils/api.py의 서버 클래스를 찾을 수 있습니다. 서버를 호출하여 서비스와 상호 작용하기 위해 데이터를 제출합니다. 총 3가지 종류가 있습니다.
사용자 방법 사용자 방법
sqlmap 핵심 상호 작용 기능 핵심 상호 작용 기능
제출할 수 있는 데이터 유형은 다음과 같습니다. 4.1, 사용자 방법
@get("/ task/new")
@get("/task/new") def task_new(): """ Create a new task """ taskid = encodeHex(os.urandom(8), binary=False) remote_addr = request.remote_addr DataStore.tasks[taskid] = Task(taskid, remote_addr) logger.debug("Created new task: '%s'" % taskid) return jsonize({"success": True, "taskid": taskid})
@get("/task/<taskid>/delete") def task_delete(taskid): """ Delete an existing task """ if taskid in DataStore.tasks: DataStore.tasks.pop(taskid) logger.debug("(%s) Deleted task" % taskid) return jsonize({"success": True}) else: response.status = 404 logger.warning("[%s] Non-existing task ID provided to task_delete()" % taskid) return jsonize({"success": False, "message": "Non-existing task ID"})</taskid>
@get("/option/list")
@post(" /option/get" )
@get("/scan/status")@post("/option/<taskid>/set") def option_set(taskid): """ Set value of option(s) for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if request.json is None: logger.warning("[%s] Invalid JSON options provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid JSON options"}) for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) logger.debug("(%s) Requested to set options" % taskid) return jsonize({"success": True})</taskid>로그인 후 복사@post("/scan/start")
@post("/scan/<taskid>/start") def scan_start(taskid): """ Launch a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_start()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if request.json is None: logger.warning("[%s] Invalid JSON options provided to scan_start()" % taskid) return jsonize({"success": False, "message": "Invalid JSON options"}) # Initialize sqlmap engine's options with user's provided options, if any for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) # Launch sqlmap engine in a separate process DataStore.tasks[taskid].engine_start() logger.debug("(%s) Started scan" % taskid) return jsonize({"success": True, "engineid": DataStore.tasks[taskid].engine_get_id()})</taskid>로그인 후 복사@get("/scan/stop")
@get("/scan/<taskid>/stop") def scan_stop(taskid): """ Stop a scan """ if (taskid not in DataStore.tasks or DataStore.tasks[taskid].engine_process() is None or DataStore.tasks[taskid].engine_has_terminated()): logger.warning("[%s] Invalid task ID provided to scan_stop()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) DataStore.tasks[taskid].engine_stop() logger.debug("(%s) Stopped scan" % taskid) return jsonize({"success": True})</taskid>로그인 후 복사@get ("/scan/kill")
@get("/scan/<taskid>/kill") def scan_kill(taskid): """ Kill a scan """ if (taskid not in DataStore.tasks or DataStore.tasks[taskid].engine_process() is None or DataStore.tasks[taskid].engine_has_terminated()): logger.warning("[%s] Invalid task ID provided to scan_kill()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) DataStore.tasks[taskid].engine_kill() logger.debug("(%s) Killed scan" % taskid) return jsonize({"success": True})</taskid>로그인 후 복사
@get("/scan/<taskid>/status") def scan_status(taskid): """ Returns status of a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_status()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if DataStore.tasks[taskid].engine_process() is None: status = "not running" else: status = "terminated" if DataStore.tasks[taskid].engine_has_terminated() is True else "running" logger.debug("(%s) Retrieved scan status" % taskid) return jsonize({ "success": True, "status": status, "returncode": DataStore.tasks[taskid].engine_get_returncode() })</taskid>
@get("/scan/<taskid>/data") def scan_data(taskid): """ Retrieve the data of a scan """ json_data_message = list() json_errors_message = list() if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_data()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) # Read all data from the IPC database for the taskid for status, content_type, value in DataStore.current_db.execute("SELECT status, content_type, value FROM data WHERE taskid = ? ORDER BY id ASC", (taskid,)): json_data_message.append({"status": status, "type": content_type, "value": dejsonize(value)}) # Read all error messages from the IPC database for error in DataStore.current_db.execute("SELECT error FROM errors WHERE taskid = ? ORDER BY id ASC", (taskid,)): json_errors_message.append(error) logger.debug("(%s) Retrieved scan data and error messages" % taskid) return jsonize({"success": True, "data": json_data_message, "error": json_errors_message})</taskid>
@get("/admin/list") @get("/admin/<token>/list") def task_list(token=None): """ Pull task list """ tasks = {} for key in DataStore.tasks: if is_admin(token) or DataStore.tasks[key].remote_addr == request.remote_addr: tasks[key] = dejsonize(scan_status(key))["status"] logger.debug("(%s) Listed task pool (%s)" % (token, "admin" if is_admin(token) else request.remote_addr)) return jsonize({"success": True, "tasks": tasks, "tasks_num": len(tasks)})</token>
@get("/admin/flush") @get("/admin/<token>/flush") def task_flush(token=None): """ Flush task spool (delete all tasks) """ for key in list(DataStore.tasks): if is_admin(token) or DataStore.tasks[key].remote_addr == request.remote_addr: DataStore.tasks[key].engine_kill() del DataStore.tasks[key] logger.debug("(%s) Flushed task pool (%s)" % (token, "admin" if is_admin(token) else request.remote_addr)) return jsonize({"success": True})</token>
sqlmapapi.py는 http 요청 항목을 편리하게 제공하지만, 사용하면 주입 중에 각 인터페이스에 대해 어떤 종류의 요청이 시작되는지에 대한 최종 결과만 얻을 수 있습니다. 스캐닝이 몇개나 되는지 요청이 어렵네요. sqlmap 소스코드를 정리해서 기록한 순서도를 공유해보겠습니다. 그림에서 페이로드 수준 요청의 특정 위치를 찾을 수 있습니다. 어떤 요청 종류와 요청 수를 알고 싶다면 여기에 사용자 정의 코드만 추가하면 됩니다.
위 내용은 sqlmapapi를 사용하여 스캔을 시작하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!