RASP Study Note 2019-11-15 07:38:45 Steven Xeldax > rasp 学习笔记 ## RASP原理 RASP最大的特性就是将自身注入到应用程序中,与应用程序融为一体,实时监测,阻断攻击,使程序自身拥有保护能力。 RASP使的防护级别降低到框架层级,现主流RASP主要设计思路大致分为Hook函数检测输入输出,修改虚拟机或者解释器等手段。 ### php RASP php RASP设计思路直接,基本就是跟踪了所有的输入点,例如跟踪HTTP请求中的所有参数,Header等一切client可以控制的变量,同时跟踪了这些变量的信息流动路径。怎么跟踪?Hook 在PHP解释器中,全局变量都保存在一个HashTable类型的符号表symbol_table中,包括预定义变量$GOBALS,$_GET,$_POST等。我们利用变量结构体中的flag中未被使用的一位来标识这个变量是否被污染。 在php中可以从两个层面hook函数,一是通过修改zend_internal_function的handler来hook PHP中的内部函数,handler指向的函数用c或者c++编写,可以直接执行。通过修改zend_internal_function结构体中handler的指向,待完成我们需要的操作后再调用原来的处理函数既可以完成hook。 另一种是hook opcode,需要使用zend提供的API zend_set_user_opcode_handler来修改opcode的handler来实现。 ``` //zend_complie.h typedef struct _zend_internal_function { /* Common elements */ zend_uchar type; zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */ uint32_t fn_flags; zend_string* function_name; zend_class_entry *scope; zend_function *prototype; uint32_t num_args; uint32_t required_num_args; zend_internal_arg_info *arg_info; /* END of common elements */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); //函数指针,展开:void (*handler)(zend_execute_data *execute_data, zval *return_value) struct _zend_module_entry *module; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; } zend_internal_function; ``` #### 补充:php hook的若干方法 ``` php内核中有几个常见的变量操作宏 CG -> Complier Global 编译时信息,包括函数表等(zend_globals_macros.h:32) EG -> Executor Global 执行时信息(zend_globals_macros.h:43) PG -> PHP Core Global 主要存储php.ini中的信息 SG -> SAPI Global SAPI信息 Zend引擎将php函数分为5种类型 #define ZEND_INTERNAL_FUNCTION 1 #define ZEND_USER_FUNCTION 2 #define ZEND_OVERLOADED_FUNCTION 3 #define ZEND_EVAL_CODE 4 #define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5 ``` ##### 针对OP进行hook 在php内核中,每一个OP操作都是由一个固定的Handler函数去负责的,看_zend_op的结构体属性第一个就是opcode_handler_t,表示该OP对应的handler函数具体是哪个。 主要是调用zend_set_user_opcode_handler,将对应的zend op的handler函数替换成自己定义的函数实现HOOK机制。 比如我们对ZEND_ECHO这条OP指令进行HOOK,即调用如下语句: zend_set_user_opcode_handler(ZEND_ECHO, hook_echo_handler); 这时候当php执行zend_echo指令的时候就会先调用我们的handler函数,这样就实现了hook。 ##### 针对FCALL进行hook 很多php内置函数的底层都是ZEND_FCALL进行实现的。 因此,我们需要HOOK两个OP,ZEND_DO_FCALL和ZEND_DO_FCALL_BY_NAME hook: (1) 从EG(current_excute_data)->function_state.function中获取原有的函数。 (2) 然后分直接方法调用和类方法调用来执行HOOK操作 (3) HOOK完成后,恢复原有函数 ##### 针对PHP_FUNCTION进行HOOK 在PHP扩展中定义函数别名,然后初始化时从function_table中删除原有的函数定义,并且注册我们自己编写的扩展函数,在执行HOOK操作之后,再恢复原有的内置函数即可。 internal_function是保存内置函数的属性,在恢复原有函数的时候手动调用一次即可。 ## OpenRASP搭建 ### 部署顺序 #### RASP Cloud 1. 安装数据库 MongoDB 版本大于等于 3.6 ElasticSearch 版本大于等于 5.6,小于 7.0 2. 确认配置 ``` [prod] EsAddr = http://127.0.0.1:9200 EsUser = EsPwd = MongoDBAddr = 127.0.0.1:27017 MongoDBUser = MongoDBPwd = ``` 3. run ``` ./rasp-cloud -d goto http://your-ip:8086 login openrasp/admin@123 ``` #### RASP客户端 java ``` 1. 下载 Java Agent 安装包 curl https://packages.baidu.com/app/openrasp/release/1.2.1/rasp-java.tar.gz -o rasp-java.tar.gz tar -xvf rasp-java.tar.gz cd rasp-*/ 2. 执行 RaspInstall 进行安装 java -jar RaspInstall.jar -install /path/to/tomcat -appid bc6c5a361ef3f419661998709b4ce584cc829061 -appsecret bnJ1BHJp7vSwcaoZdTZaGKdLom5rual1frD1CmK9Hzk -backendurl http://192.168.56.163:8080/ 3. 重启 Tomcat/JBoss/SpringBoot 应用服务器 /path/to/tomcat/bin/shutdown.sh /path/to/tomcat/bin/startup.sh ``` php ``` 1. 下载 PHP 安装包 curl https://packages.baidu.com/app/openrasp/release/1.2.1/rasp-php-linux.tar.bz2 -o rasp-php-linux.tar.bz2 tar -xvf rasp-php-linux.tar.bz2 cd rasp-*/ 2. 执行 install.php 进行安装 php install.php -d /opt/rasp --app-id bc6c5a361ef3f419661998709b4ce584cc829061 --app-secret bnJ1BHJp7vSwcaoZdTZaGKdLom5rual1frD1CmK9Hzk --backend-url http://192.168.56.163:8080/ 3. 重启 PHP-FPM 或者 Apache 服务器 service php-fpm restart -或者- apachectl -k restart ``` #### IAST工具 ``` sudo sysctl -w vm.max_map_count=262144 ``` need python3 ``` pip3 install --upgrade git+https://github.com/baidu-security/openrasp-iast ``` or pyinstaller ``` wget https://packages.baidu.com/app/openrasp/openrasp-iast-latest -O /usr/bin/openrasp-iast ``` ``` 1. 下载或者升级 Fuzz 工具 pip3 install --upgrade git+https://github.com/baidu-security/openrasp-iast 2. 配置 MySQL 服务器 - 使用 MySQL root 账号执行以下命令授权 DROP DATABASE IF EXISTS openrasp; CREATE DATABASE openrasp default charset utf8mb4 COLLATE utf8mb4_general_ci; grant all privileges on openrasp.* to 'rasp'@'%' identified by 'rasp123'; grant all privileges on openrasp.* to 'rasp'@'localhost' identified by 'rasp123'; 3. 配置 Fuzz 工具 - 请修正 MySQL 服务器地址 openrasp-iast config -a bc6c5a361ef3f419661998709b4ce584cc829061 -b bnJ1BHJp7vSwcaoZdTZaGKdLom5rual1frD1CmK9Hzk -c http://192.168.56.163:8080/ -m mysql://rasp:rasp123@127.0.0.1/openrasp 4. 启动 Fuzz 工具 openrasp-iast start -f -或者后台启动- openrasp-iast start ``` ### 访问 Cloud总控制台http://localhost:8080 IAST后台http://localhost:18664 ### 参考出处 https://c0d3p1ut0s.github.io/一类PHP-RASP的实现/ https://blog.csdn.net/u011721501/article/details/70174924 http://blog.nsfocus.net/rasp-tech/ https://blog.csdn.net/dengzhasong7076/article/details/102139799