毕业设计之php RASP(二) 威胁判断

 

正文

先感谢0kee的大哥指导 ~

这里分为三个部分
1、获取函数的参数值
2、对http传入值的获取,($_GET$_POST$_COOKIE)
3、如何判断存在威胁(词法分析、污染标记)

函数参数获取

Zend中有接口可以获取到参数:zend_parse_parameterszend_get_parameters_ex

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &cmd, &cmd_len, &ret_code) == FAILURE) {
 return;
}

或者
zend_get_parameters_ex(argc, &command) == SUCCESS

可以跟进看一下

static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) 
arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));

或者

ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
{
    void **p;
    int arg_count;
    va_list ptr;
    zval ***param;
    TSRMLS_FETCH();

    p = zend_vm_stack_top(TSRMLS_C) - 1;
    arg_count = (int)(zend_uintptr_t) *p;

    if (param_count>arg_count) {
        return FAILURE;
    }

    va_start(ptr, param_count);
    while (param_count-->0) {
        param = va_arg(ptr, zval ***);
        *param = (zval **) p-(arg_count--);
    }
    va_end(ptr);

    return SUCCESS;
}

可以看到它其实就是从Zend虚拟机的vm栈顶上面获取参数。

当然也可以通过php运行时的一些结构,比如EG(argument_stack)

void **p = EG(argument_stack)->top ;

函数的参数个数保存在int arg_count = opline->extended_value;中,拿到参数个数之后,我们就可以移动指针了。

比如获取该函数的各个参数,也就是函数的调用约定,表达式为:

zval *arg1 = *((zval**)(p - arg_count));   //参数1
zval *arg2 = *((zval**)(p - (arg_count - 1)));  //参数2
zval *arg3 = *((zval**)(p - (arg_count - 2)));  //参数3

例如:

root@ubuntu:/var/www/html/bishe# cat 1.php 
<?php
echo str_replace("world","Shanghai","Hello world!");

HTTP数据获取

从php5.4开始后就自带了一个小型的server,所以可以对它进行调试

gdb /opt/php_debug/bin/php
set args -S 0.0.0.0:1234
run
按ctrl + c
b lemon_php_http_request
run

对于如何从php扩展中获取$_GET$_POST等值,鸟哥一篇博文已经有了分析。

http的信息存在在http_globals,文件位置:php-src-php-5.5.9/main/php_globals.h

#define TRACK_VARS_POST		0
#define TRACK_VARS_GET		1
#define TRACK_VARS_COOKIE	2
#define TRACK_VARS_SERVER	3
#define TRACK_VARS_ENV		4
#define TRACK_VARS_FILES	5
#define TRACK_VARS_REQUEST	6

比如访问:

http://love.lemon:1234/1.php?i=iam&i1=lemon

PG(http_globals)[TRACK_VARS_GET]中获取GET请求的数据,它也是一个hash table

ulong ikey;
char *skey;
zval **data;
HashTable *h;
zval *arr;

arr = PG(http_globals)[TRACK_VARS_GET];
h = HASH_OF(arr);

for (zend_hash_internal_pointer_reset(h);
     zend_hash_has_more_elements(h) == SUCCESS;
     zend_hash_move_forward(h))
{
  zend_hash_get_current_data(h, (void**)&data);
  zend_hash_get_current_key(h, &skey, &ikey, 0);
} 

威胁判断

这部分属于最难做的地方,如果不够精确的话,很影响最后的结果。如果要做bypass的话,可以重点研究此部分。

污染标记

可以在PHP_RINIT_FUNCTION进行设置,也就是有请求的时候将所有的数据都标记为污染数据,然后再进入流程后可根据一些函数操作来消除标记,最后进入危险函数的时候看污染标记是否存在来确认威胁。

b lemon_php_mark_strings

这里想要加上一个标记就需要了解一下php变量的结构体

typedef struct _zval_struct zval;
typedef union _zvalue_value {
	long lval;					/* long value */
	double dval;				/* double value */
	struct {
		char *val;
		int len;
	} str;
	HashTable *ht;				/* hash table value */
	zend_object_value obj;
} zvalue_value;

struct _zval_struct {
	/* Variable information */
	zvalue_value value;		/* value */
	zend_uint refcount__gc;
	zend_uchar type;	/* active type */
	zend_uchar is_ref__gc;
};

变量的值是存在_zvalue_value中,这里使用联合体也是为了空间利用考虑,因为一个变量同时只能属于一种类型,至于_zval_struct里面的就是变量的一些说明,比如变量类型,是否被引用等。很蛋疼的事情就是在这里面每个字段都有明确的意义,没有一个预留的字段。

鸟哥的taint这里的做法则是把字符串的长度扩充一个int, 然后用magic number做标记写到后面去

Z_STRVAL_PP(ppzval) = erealloc(Z_STRVAL_PP(ppzval), Z_STRLEN_PP(ppzval) + 1 + PHP_TAINT_MAGIC_LENGTH);
PHP_TAINT_MARK(*ppzval, PHP_TAINT_MAGIC_POSSIBLE);

但是要追踪污染标记是很复杂的,因为经过比如字符串拼接,各种处理的函数,编码之类的后就得重新打上标记。这块也可以看上一篇如何去hook,再进行字符串处理的时候再进行标记一次或者比如进入了intval就取消标记。

但是毕设我就偷懒一点吧,简单的判断一下Http输入值能不能完整进入函数参数。

<?php
$a = @$_GET['i'];
$b = "sys"."tem";
$b("echo ".$a." iaml3m0n ");

posted @   l3m0n  阅读(1895)  评论(0编辑  收藏  举报
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
L3m0n
点击右上角即可分享
微信分享提示