查阅大量资料后,列出的常见代码审计漏洞。
代码审计 =================================================================================================== * sql注入 ** 变量未过滤导致 *** http://www.test404.com/post-811.html - $_SERVER变量未过滤,请求头中X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE - 传入的参数未强制转为int - 数组只过滤了value未过滤key,但key也会代入到sql中 - $_FILES变量未过滤( http://www.test404.com/post-815.html ) ** 过滤函数的误用 *** http://www.test404.com/post-809.html - str_replace将单引号去掉了,结果转义符反斜杠留下了,导致在sql语句中将真正的单引号转义了 - 在带入sql语句前,stripslashes将转义符去掉了 - 多余的urldecode,导致单引号的“二次编码”%2527可以绕过单引号过滤 ( http://www.test404.com/post-808.html ) ** 二次注入 - 单引号被转义后入库或入文件,再次以该字段为查询条件时触发 ** 宽字节注入 - gpc或addslash添加了转义符%5c * 命令注入 - popen - proc_open - exec - system - passthru - 反引号 * 代码注入 ** pgrep_replace ** eval ** assert ** 双引号 - php -r '$a = "${${eval(phpinfo())}}";' - php -r '$a = "${@eval(phpinfo())}";' - php -r '$a = ${@eval("phpinfo();")}; - php -r '$a = ${${eval("phpinfo();")}};' * xss反射 ** 直接回显 $_SERVER['HTTP_REFFER'] ** $_SERVER['PHP_SELF'] ** $_SERVER['HTTP_URI'] ** $_SERVER['USER_AGENT'] * xss存储 ** 留言板未使用 htmlspecialchars 过滤 * CSRF 利用了网站对用户的信任 ** 敏感表单未加token验证 ** 防御 - 不要采用get方式提交 - 添加令牌验证 - 验证请求来源,http_reffer,但可被绕过 - 在http头部添加自定义属性来验证 * 文件包含 ** 本地包含,受gpc影响 - 技巧 %00截断 ** 远程包含,需要php.ini中 allow_url_include 与 allow_url_fopen 开启 - 技巧:追加 ? # 等字符 ** 伪协议 - php://input,并post提交<?php phpinfo();?>, 需要allow_url_inlcude开启且php>5.2.0 - php://filter/read=convert.base64-encode/resource=based64-php-code.txt, 无需什么条件 * 动态函数执行与匿名函数执行 ** 动态函数:函数名以参数形式传进来,直接跟括号得到调用。 ** 匿名函数:类似lambda函数,但函数体在在定义时引入了外部字符串变量,使得可以注入恶意代码。 * 反序列化漏洞 ** 构造的序列化字符串在反序列化后会覆盖类的成员变量。结合其他代码执行漏洞,得到利用。 * 变量覆盖漏洞 ** 如果自动注册全局变量默认开启,地址栏提交的参数会被定义成变量。 - 变量未初始化时,会被覆盖,可导致修改module之类的变量,导致文件包含漏洞; ** 动态定义变量 - http://www.test404.com/post-815.html - 使用双美元符$$,动态定义变量时。 - 危险函数extract,会从字典中动态提取键值对来定义变量 * 文件管理漏洞 ** 危险函数copy、unlink,存在时间竞争漏洞。 - http://www.test404.com/post-875.html - 上传头像-->生成临时文件(tmp.php)-->不断请求tmp.php(在上层目录生成shell.php文件)-->删除当前目录下tmp.php等非jpg文件,但留下了上层目录下的shell.php文件-->成功! * 上传漏洞 ** 危险函数:比如getimagesize,如果文件头部以GIF89a开头,那么该文件就被判断为图片文件。 - 参见 http://www.test404.com/post-875.html ** 未授权引用:比如直接访问上传接口 * 验证码漏洞 ** 抓包构造sid,发送空验证码,可绕过条件判断 - 不通过页面访问时,没生成验证码,弱类型比较时NULL==''为真 ** 第一次通过页面刷新获取验证码,后续抓包反复提交该验证码 - 无论验证码是否输入正确与否,后台都应该重新生成验证码 * php中的奇怪现象 ** 弱类型比较时存在绕过判断条件的漏洞 *** 传递的参数为数组时,函数一般返回为NULL。 - ?goods[]=92%004&goods[]=967&goods[]=993 $_GET: array(1) { ["goods"]=> array(3) { [0]=> string(4) "924" [1]=> string(3) "967" [2]=> string(3) "993" } } $_GET["goods"]: array(3) { [0]=> string(4) "924" [1]=> string(3) "967" [2]=> string(3) "993" } ereg('123', '456'): bool(false) ereg("^[0-9a-zA-Z]+$", $_GET["goods"]): NULL ereg("^[0-9a-zA-Z]+$", $_GET["goods"])!==False: bool(true) ereg("^[0-9a-zA-Z]+$", $_GET["goods"])!=False: bool(false) $_GET["goods"]>9999999: bool(true) strcmp($_GET["goods"], "123123"): NULL strcmp($_GET["goods"], "123123")==0: bool(true) *** 弱类型的比较 - var_dump("1e8">999): bool(true) - var_dump("1e8">"999"): bool(true) - var_dump("1e8asdfasdf">999): bool(true) - var_dump("1e8asasdf">"999"): bool(false) - var_dump("0e8"==0): bool(true) - var_dump("0e8"=="0"): bool(true) - var_dump(true=="asfasdfsfsadf"): bool(true)