代码审计
===================================================================================================
* 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
)