移动安全 安全管理 应用案例网络威胁 系统安全 应用安全 数据安全 云安全
当前位置: 主页 > 信息安全 > 网络威胁 >

黑客经验之谈PHP4内核Hacking

时间:2011-05-03 15:15来源: 点击:
此篇文章记录一下我这些天PHP HACKING的经验,乱七遭八的。各位看官莫见笑,有问题多交流。
TagsHacking(7)  

  此篇文章记录一下我这些天PHP HACKING的经验,乱七遭八的。各位看官莫见笑,有问题多交流。

  先大概描述一下PHP内核的情况,PHP内核分为2个部分,ZEND和PHP CORE。ZEND可以说是PHP的内核的内核,他负责与沟通。分配内存,初始化什么什么的,他就负责了,同时把可读的脚本代码系统化。而PHP CORE呢,负责一些外围处理,比如与SAPI沟通。APACHE、IIS啊之类的东西。php.ini他也管。 还负责网络和文件I/O。最后提醒一句,PHP是用C写的,而不是C++,大多数资源,类型,在PHP内核中需要转换。

  在C语言中,套接字这样定义:SOCKET socket(int af,int type,int protocol);

  在PHP中是:

  typedef int PHP_SOCKET;

  typedef struct {

  PHP_SOCKET bsd_socket;

  int type ;

  int error;} php_socket;

  看起来是一样的。那就来看看一个最简单的网络函数。

  PHP_FUNCTION(socket_write)

  {

  zval *arg1;

  php_socket *php_sock;

  int retval, str_len;

  long length;

  char *str;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str,

  &str_len, &length) == FAILURE)

  return;

  ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name,

  le_socket);

  if (ZEND_NUM_ARGS() < 3) {

  length = str_len;

  }

  #ifndef PHP_WIN32

  retval = write(php_sock->bsd_socket, str, MIN(length, str_len));

  #else

  retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);

  #endif

  if (retval < 0) {

  PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);

  RETURN_FALSE;

  }

  RETURN_LONG(retval);

  }

  先说zval,ZVAL是PHP内核中的结构,里面包含任何数据类型。所以在PHP内核中最好用ZVAL,而少用char *。这样可能会带来一些安全问题。看上面的代码,好象是没问题。其实不然,看char * str。他作为第2个参数被传入。

  执行socket_write ( $sock, "hellosdfs35434sdvx.plpop34][[]" );

  正常得很。但是如果我们提交一个PHP数组他就会暴错了。为什么呢?虽然说char str[]从某种意义上等于char * str。但是PHP中的数组和C语言可不一样。PHP程序本身这种错误太多了,PHP的开发者可能已经习惯了。

  继续PHP SOCK.zend_parse_parameters函数是得到传入参数的,当CHAR类型被传入的时候,必须指定CHAR LEN.ZEND_NUM_ARGS()是得到函数个数的。

  那TSRMLS_CC是什么东西。这里得专门讲一下TSRM。他的全称是Thread Safe Resource Management。

  PHP是作为网络脚本来使用的,这意味着,成千上万的人在同1秒钟里可能调用同一个页面。客户A请求的是ID1,客户B请求的是ID2,以下省去数万字。

  如果没有TSRM的话,单线程的SAPI还好说,像apache,iis这样的话。那么PHP可能乱套。TSRM的作用就是保持变量的中立性。在PHP中,基本上从全局传入参数都要使用TSRM.PHP hacking中也应该使用TSRM。

  ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);

  相当于是把参数1 当做PHP_SOCK类型在ZEND注册资源。关于SOCKET_WRITE后面都是一些简单的C函数,就不谈了这个了。

  关于PHP内核里面建立套接字还有一种方法,那就是用PHP流。PHP流是很强大的,是I/O的代名词。无论是FILE I/O,还是NETWORK I/O。

  拿php_stream_open_wrapper API来说,他支持FILE、TCP、UDP、、SCP、HTTP、。

  php_stream * stream = php_stream_open_wrapper

  ("http://www.php.net", "rb", REPORT_ERRORS, NULL);

  if (stream) {

  while(!php_stream_eof(stream)) {

  char buf[1024];

  if (php_stream_gets(stream, buf, sizeof(buf))) {

  printf(buf);

  } else {

  break;

  }

  }

  php_stream_close(stream);

  }

相关文章
------分隔线----------------------------

推荐内容