PHP代码审计总结


当你的才华

还撑不起你的野心时

那你就应该静下心来学习


 

       代码审计学习线上实验,都是CE一边实操,一边整理的笔记,方便以后翻看时,可快速查阅.

       这是代码审计最后一篇,对前面所学进行总结

目录

二、代码执行漏洞

三、命令注入漏洞

四、XSS 漏洞

五、CSRF 漏洞

六、SQL注入漏洞

七、文件包含漏洞

八、文件上传漏洞

九、变量覆盖漏洞

十、身份认证漏洞

漏洞防范


二、代码执行漏洞

  • 什么是代码执行漏洞?

答:

       字符串转化成代码的函数时,没有考虑到用户是否能控制这个字符串(说白了就是未对用户输入进行过滤或过滤不严),导致用户可以将代码注入到应用中执行才导致代码执行漏洞的产生

  • 代码执行漏洞的相关函数有:eval()、 assert() 、call_user_func_array()、preg_replace() 、call_user_func()等常规函数和动态函数$a($b) (比如$_GET($_POST["xxx"]),这些函数在什么情况下会有代码执行漏洞的危险?

答:

eval() 函数没有对用户数据进行严谨的过滤会导致代码执行漏洞产生 

assert() 函数在,用户输入的参数是字符串,它将会被 assert() 当做 PHP 代码来执行

preg_replace()  函数特性的原因,如果pattern 中存在参数e修饰符时,pattern中存在参数e修饰符时,replacement 的值会被当成php代码来执行,会导致代码执行漏洞产生

触发该漏洞前提条件:

       第一个参数需要e标识符,有了它可以执行第二个参数的命令

       第一个参数需要在第三个参数中的中有匹配,不然echo会返回第三个参数而不执行命令

call_user_func() 函数并不是函数,我们这里统称为一类调用的函数,其余参数是被调用函数的参数,这一类调用函数经常用在框架中动态调用函数,一般都是较大的程序才会使用到这类函数。只要第一个参数 callback 是被调用的函数,其余参数是被调用函数的参数,其实我们有时只需要调用一个,这个一般是开发人员为了方便自己使用和调用静态方法时才会使用,这样就导致了代码执行漏洞的 产生

call_user_func_array()

        跟call_user_func 类似

call_user_func(),call_user_func_array() 主要区别,参数格式

//call_user_func(array($foo, 'test'), [$param, $param1, $param2])
这种格式会把后面数组作为一个参数传递过去

//call_user_func_array(array($foo, 'test'), [$param, $param1, $param2]) 
这种格式会作为三个参数传递给回调函数,如果存在key ,忽略。

       变量函数和普通函数调用(literal function)速度差别不大,和call_user_func相差有一倍以上,而call_user_func_array则要更慢。所以你给的代码才会尽量避免使用call_user_func_array而更倾向于使用变量函数。因为只有很少的函数会有5个以上的参数,所以上面代码里才把1到5个函数的调用用变量函数来写,而只留下小部分的函数用call_user_func_array调用,从而最大的加快程序执行速度.

在类方法参数个数不确定时,还是得使用 call_user_func_array() !

 

动态函数 例如获取 get 方式传递的变量名为 id 的变量值作为函数名,而变量 $_GET['data'] 则获取 get 方式传递的变量名为 data 的变量值作为函数的参数,这样看似很方便,但实则安全有很大问题

  • PHP代码执行漏洞和 Sql注入、PHP命令注入漏洞的区别是什么?

答:

       Sql注入漏洞是将Sql语句注入到后台数据库中进行解析并执行

       命令注入漏洞是指注入可以执行的系统命令(如windows中的CMD命令、linux中的Bash命令)并执行

       PHP代码执行漏洞是将PHP代码注入到Web应用中通过Web容器执行

  • 针对这个漏洞,应该如何防范?

答:

       使用白名单+正则表达式的方式对用户输入进行过滤,

另外:

  • 使用json保存数组,当读取时就不需要使用eval了

  • 对于必须使用eval的地方,一定严格处理用户数据

  • 字符串使用单引号包括可控代码,插入前使用addslashes转义

  • 放弃使用preg_replace的e修饰符,使用preg_replace_callback()替换

  • 若必须使用preg_replace的e修饰符,则必用单引号包裹正则匹配出的对象

 

三、命令注入漏洞

  • 什么是命令注入漏洞?

答:

       由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至Web应用程序中,并利用该方式执行外部程序或系统命令实施攻击,非法获取数据或者网络资源等

  • 相关函数有:system()、exec()、passthru()、shell_exec()、popen()、proc_open()、pcntl_exec()一共7个函数。这些函数被分为三类,分别在什么情况下会有命令注入漏洞的危险?

答:

       第一类漏洞:

              可以直接传入命令执行并返回结果,其中system()最简单,不需要输出函数,会自动打印命令执行结果

       第二类漏洞:

              可以指向进程的管道,该进程由派生给定的 command 命令执行而产生(系统的漏洞造成命令注入)

       第三类漏洞

              在当前进程空间执行指定程序。当发生错误时返回 FALSE,没有错误时没有返回。(调用的第三方组件存在代码执行漏洞)

  • 针对这个漏洞,应该如何防范?

答:

       用白名单对用户输入进行过滤

除此之外这里有几项具体的建议:

  1. 使用自定义函数或函数库来替代外部命令的功能

  2. 使用 escapeshellarg()函数来处理命令参数

  3. 使用 safe_mode_exec_dir 指定可执行文件的路径

 

四、XSS 漏洞

  • 什么是 XSS 攻击 ?

答:

       恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的

  • XSS 攻击被分为两种类型:反射性XSS和存储型XSS,他们之间的区别是什么?

答:

       反射型XSS是即时响应,对网站造成的危害不大,且反射型XSS要考虑绕过浏览器的过滤问题,屏蔽性比存储型要差

       存储型XSS则需要先把利用代码保存在比如数据库或文件中,当web程序读取利用代码时再输出在页面上执行利用代码,且存储型XSS不用考虑绕过浏览器的过滤问题,屏蔽性也要好很多

  • XSS 漏洞和PHP输出函数密切相关,常见的输出函数有: echo printf print print_r sprintf die var-dump var_export

  • 针对这个漏洞,应该如何防范?

答:

反射型xss漏洞防范

A.PHP直接输出html的,可以采用以下的方法进行过滤:

  •   1.htmlspecialchars函数
  •   2.htmlentities函数
  •   3.HTMLPurifier.auto.php插件
  •   4.RemoveXss函数

B.PHP输出到JS代码中,或者开发Json API的,则需要前端在JS中进行过滤:

  •   1.尽量使用innerText(IE)和textContent(Firefox),也就是jQuery的text()来输出文本内容
  •   2.必须要用innerHTML等等函数,则需要做类似php的htmlspecialchars的过滤

C.其它的通用的补充性防御手段

  •   1.在输出html时,加上Content Security Policy的Http Header
    (作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)
    (缺陷:IE或低版本的浏览器可能不支持)
  •   2.在设置Cookie时,加上HttpOnly参数
    (作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6)
    (缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全)
  •   3.在开发API时,检验请求的Referer参数
    (作用:可以在一定程度上防止CSRF攻击)
    (缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)

存储型xss漏洞防范

存储型XSS对用户的输入进行过滤的方式和反射型XSS相同

使用htmlspecialchars() 函数 演示:

      htmlentities() :把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体

htmlspecialchars和htmlentities的区别:

       htmlspecialchars 只转义 & 、" 、' 、< 、> 这几个html代码,而 htmlentities 却会转化所有的html代码,连同里面的它无法识别的中文字符也会转化

 

五、CSRF 漏洞

  • 什么是 CSRF 攻击 ?

答:

 伪装来自受信任用户的请求来利用受信任的网站

  • CSRF 常和 XSS 混为一谈,其实他们的攻击原理完全不一样,他们之间的区别是什么?(比如XSS必须用到javascript,而CSRF不一定需要)

  •     • XSS: XSS漏洞——构造payload——发送给受害人——受害人点击打开——攻击者获取受害人的cookie——攻击者使用受害人cookie完成攻击

           • CSRF: CSRF漏洞——构造payload——发送给受害人——受害人点击打开——受害人执行代码——受害人完成攻击(不知情)

  • 针对这个漏洞,应该如何防范?

答:

服务器端防御CSRF攻击主要有四种策略:

  • 验证HTTP Referer 字段
  • 在请求地址中添加token并验证
  • 在HTTP头中自定义属性并验证
  • 添加验证码并验证

 

六、SQL注入漏洞

  • 什么是 SQL注入漏洞 ?

答:

       通过构建特殊的输入作为参数传入Web应用程序,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统

  • SQL注入攻击的分类?常见的有哪几种类型?

答:

SQL注入两大分类:

      普通SQL注入

      编码SQL注入

常见类型:

      宽字节注入

      报错注入

      延时注入

      普通注入

  • 针对这个漏洞,应该如何防范?

宽字节注入防御

对于宽字节注入,有如下几种防御方式:

  • 使用mysql_set_charset函数设置连接所使用的字符集,再调用mysql_real_escape_string来过滤用户输入。

  • 将character_set_client设置为binary(二进制)

  • 使用参数化查询、pdo查询

其它的大同小异,就是使用白名单对用户数据进行过滤

 

七、文件包含漏洞

  • 什么是文件包含漏洞?

答:

       开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用, 但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,而我们可以构造这个恶意文件来达到邪恶的目的,造成文件包含漏洞

  • 文件包含漏洞的分类?它们之间的区别是什么?

答:

分为本地文件包含和远程文件包含,两大分类

      本地文件包含:包含本地文件,主要出现在模块加载、模板加载和cache调用之处

      远程文件包含:包含的文件位于远程服务器上,需要设置allow_url_include = on

 

  • 文件包含相关函数有: include() require() include_once() require_once(),它们之间的区别是什么?

答:

   include():

       执行到include时才包含文件,找不到被包含文件时只会产生警告,代码会继续执行

   require():

       程序开始运行就预先包含文件,找不到被包含的文件时会产生致命错误,并停运行

   include_once()和require_once():

       功能和上面一样,但文件中代码已被包含则不会再次包含

 

  • 针对这个漏洞,应该如何防范?

答:

防御主要有两种方法:

  • 采用白名单的方式将允许包含的文件列出来,只允许包含白名单中的文件,这样就可以避免任意文件包含的风险。
  • 采用白名单的方式将文件包含漏洞利用过程中的一些特殊字符定义在黑名单中,对传入的参数进行过滤,但这样有时会因为过滤不全,导致被有经验的攻击者绕过

 

八、文件上传漏洞

  • 什么是文件上传漏洞?

答:

       是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力

  • 文件上传相关函数只有:move_uploaded_file(),在什么情况下会出现文件上传漏洞?

答:

       没有限制上传的文件格式,导致可以直接上传危险文件

  • 针对这个漏洞,应该如何防范?

文件上传漏洞防御有以下几种:

        1、文件上传的目录设置为不可执行

       2、判断文件类型

       3、使用随机数改写文件名和文件路径

       4、单独设置文件服务器的域名

 

九、变量覆盖漏洞

  • 什么是变量覆盖漏洞?应该怎么利用?

答:

        变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击

  • 变量覆盖漏洞相关函数有: :extract(), parse_str()和import_request_variables(),他们在什么情况下会有变量覆盖的危险?

答:

extract()函数

  • 当第二个参数为空或者EXTR_OVERWRITE时,变量注册如果遇到冲突会直接覆盖掉原变量。

  • 当第二个变量为EXTR_IF_EXISTS时,仅当原变量已存在是对其进行更新,否则不注册新变量。

parse_strc()函数

该函数在注册变量之前不会验证当前变量是否已存在,如果存在会直接覆盖

import_request_variables()函数

将 GET/POST/Cookie 变量导入到全局作用域中,import_request_variables()函数函数只能用在 PHP4.1 ~ PHP5.4之间

  • 针对这个漏洞,应该如何防范?

答:

extract()函数防御

       将extract.php中extract()函数第二个参数修改为extr_skip:

parse_str()函数防御

       parse_str()函数的防范,自己添加判断语句

mport_request_variables()函数防御

       此函数是非常危险的函数,在PHP5.5之后已被官方删除!假如你任然在使用低版本的PHP环境,也建议你避免使用此函数

 

十、身份认证漏洞

  • 什么是身份认证漏洞?

答:

       认证的目的是为了认出用户是谁,而授权的目的是为了决定用户能够做什么,身份认证实际上就是一个验证凭证的过程

  • 身份认证最常用的是cookie·session,他们之间的区别是什么?分别对应什么漏洞?

答:

       Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中

       Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式

 

  • 针对这个漏洞,应该如何防范?

答:

漏洞防范

cookie身份认证漏洞防范

单纯的cookie容易被修改,添加session变量对cookie进行验证

session固定漏洞防御

常见的防御方案有如下几种:

  • 1、更改Session名称。PHP中Session的默认名称是PHPSESSID,此变量会保存在Cookie中,如果攻击者不分析站点,就不能猜到Session名称,阻挡部分攻击。

  • 2、关闭透明化Session ID。透明化Session ID指当浏览器中的Http请求没有使用Cookie来存放Session ID时,Session ID则使用URL来传递。

  • 3、设置HttpOnly。通过设置Cookie的HttpOnly为true,可以防止客户端脚本访问这个Cookie。

  • 4、每当用户登陆的时候就进行重置sessionID

  • 5、sessionID闲置过久时,进行重置sessionID


我不需要自由,只想背着她的梦

一步步向前走,她给的永远不重


 

你可能感兴趣的:(渗透测试,PHP,代码审计,渗透基础篇)