아래는 트리거 예제입니다.
테스트 테이블을 생성합니다.
test 테이블에는 데이터를 넣어 놓고,
test2 테이블에는 구조만 같게 해 놓고 데이터는 넣지 않습니다.
그리고 트리거 설정 후 부터는 test 에 insert 되는 데이터를 test2 에도 insert 되게 합니다.
[테스트 준비]
mysql> use test;
mysql> create table test (no int(3) AUTO_INCREMENT PRIMARY KEY, name varchar(20), age int(3));
mysql> insert test (name, age) values ('CDH', '20');
mysql> insert test (name, age) values ('JJE', '21');
mysql> create table test2 (no int(3) AUTO_INCREMENT PRIMARY KEY, name varchar(20), age int(3));
[트리거 생성]
mysql> delimiter $$
create trigger test_trigger
after insert on test for each row
begin
insert into test2 values(new.no, new.name, new.age);
end
$$
delimiter ;
[설명]
* test_trigger : 트리거 이름
* after insert : insert 되고 나서 실행 (데이터 처리 전에 실행하려면 before 를 사용)
* on test : test 테이블 연결
* for each row : 각 행마다 실행
* begin ~ end : 조건에 맞으면 begin 과 end 사이 구문 실행 (insert, update, delete 감지 가능)
* new : insert 사용시 new, delete 사용시 old, update 사용시 old, new 를 사용할 수 있습니다.
* delimiter 뒤에 오는 문자로 쿼리 마치는 문자를 정의하는 것입니다.
내용중에 세미콜론(;) 이 들어갈 수 있으니 $$ 로 변경 해놓고, 모든 작업이 완료 후 다시 ; 로 원복 하였습니다.
[참고]
* 트리거 보기
show triggers;
* 트리거 삭제
drop trigger 트리거명;
[테스트]
데이터를 추가로 입력하여 두 개의 테이블에 들어갔는지 확인합니다.
mysql> insert test (name, age) values ('CJW', '3');
mysql> insert test (name, age) values ('CHY', '5');
mysql> select * from test;
mysql> select * from test2;
[원격지 DB 테이블 연결]
mysql> 쉘 상에서는 직접적인 연결을 지원하지 않고,
내부에 원격지 테이블 연결이 가능하므로 연결을 통하여 insert 를 하면 될 것 같습니다.
(참조 : https://icoon22.tistory.com/251)
(단점 : show table testtbl 시 패스워드 노출)
CREATE TABLE testtbl (
id INT AUTO_INCREMENT PRIMARY KEY,
col1 VARCHAR(100) DEFAULT NULL,
col2 VARCHAR(200) DEFAULT NULL
) ENGINE=FEDERATED
DEFAULT CHARSET=UTF8
CONNECTION='mysql://userid:userpw@192.168.10.2:3306/testdb/testtbl;
[MySQL 에서 시스템 명령어 사용]
MySQL 에서 OS 명령어를 실행하려면 UDF 라이브러리가 필요합니다.
1) 리눅스
centos : https://ymj0078.tistory.com/5
ubuntu : https://oranke.tistory.com/273
(아래는 Ubuntu 18.04 에서 진행하였습니다)
# git clone https://github.com/mysqludf/lib_mysqludf_sys.git
# cd lib_mysqludf_sys/
# vi Makefile
LIBDIR=/usr/lib/mysql/plugin
install: gcc -Wall -I/usr/include/mysql -I. -fPIC lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so |
* OS 에 따라 /usr/lib/mysql/plugin 또는 /usr/lib64/mysql/plugin 사용
* /usr/include/mysql 디렉토리가 없는 경우
Ubuntu : apt -y install libmysqld-dev
CentOS : yum -y install mysql-devel 패키지 추가 설치
# gcc -shared -o lib_mysqludf_sys.so lib_mysqludf_sys.c -I/usr/include/mysql
# cp -arp lib_mysqludf_sys.so /usr/lib/mysql/plugin/
플러그인 추가 (mysql 로그인 후)
DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;
DROP FUNCTION IF EXISTS sys_get;
DROP FUNCTION IF EXISTS sys_set;
DROP FUNCTION IF EXISTS sys_exec;
DROP FUNCTION IF EXISTS sys_eval;
CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
확인
select * from mysql.func;
테스트
select sys_exec('touch /tmp/test_mysql');
동작이 되지 않을 경우 쉘에서 아래와 같이 입력합니다.
(참조 : https://oranke.tistory.com/273)
# apparmor_status
결과에 /usr/sbin/mysqld 를 차단하지 않았나 확인해 볼 것
등록되어있는 경우 삭제를 해야 합니다.
# ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
# apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
재확인
sudo apparmor_status
apparmor 와 mysql 재구동
# systemctl restart mysql
# systemctl restart apparmor
그리고 다시 테스트
select sys_exec('touch /tmp/test_mysql');
그렇다면 MySQL trigger 와 udf 를 합친 방법을 사용해 봅시다.
맨 위의 예제에서 begin 과 end 사이에 아래 내용을 넣으면..
begin
SET @exec_var = sys_exec(CONCAT('touch /tmp/', new.name));
end
exec_var 라는 mysql 변수에 sys_exec 결과를 넣는다는 뜻이지만 실제로 실행이 되어집니다.
CONCAT() 에 있는 'touch /tmp/' 와 콤마(,) 뒤의 new.name (새로운 name 필드값) 은 아래와 같이 이어붙인 명령이 됩니다.
insert into test (name, age) values ('cdh', '22'); 라고 입력시
=> touch /tmp/cdh 라고 시스템 명령을 수행한 것과 같습니다.
한 번 더 해보면.. (CONCAT 내의 띄어쓰기 잘 살펴볼 것)
begin
SET @exec_var = sys_exec(CONCAT('touch /tmp/', new.name, ' /tmp/', new.age));
end
insert into test (name, age) values ('cdh', '22'); 라고 입력시
=> touch /tmp/cdh /tmp/22 라고 시스템 명령을 수행한 것과 같습니다.
그래서 /tmp 디렉토리 내에 cdh 와 22 라는 파일이 생성된 것을 볼 수 있습니다.
2) 윈도우
아래 URL 은 64bit 용 dll 파일 입니다.
https://github.com/sqlmapproject/sqlmap/files/1789515/lib_mysqludf_sys_64.zip
lib_mysqludf_sys_64.zip
{mysql 설치디렉토리}\lib\plugin 안에 저장합니다.
디렉토리가 보이지 않을 경우 아래와 같이 플러그인 경로를 확인하고 실제로 존재하지 않을 경우
디렉토리를 수동으로 생성해줍니다.
mysql> select @@plugin_dir;
라이브러리 추가
mysql> use mysql;
mysql> create function sys_exec returns int soname 'lib_mysqludf_sys.so';
확인
mysql> selet * from mysql.func;
시스템 명령어 사용 예 (리눅스와 동일. 단 경로는 슬래시 두개로 사용)
1) 그냥 사용시
mysql> select sys_exec("echo aaa > c://test.txt");