0x0 前言
搭建平台使用的架构是WAMP架构
操作系统为windows7
Apache版本为2.4.39
MySQL版本为8.0.12
PHP版本为5.2.17
0x1 信息收集
1.1 探测可能存在的漏洞类型
打开网站发现几个值得关注的功能,评论留言,搜索框,注册登录功能。
猜测可能存在的漏洞:
评论留言可能存在SQL注入、XSS漏洞。
搜索框可能存在SQL注入、XSS漏洞、命令执行漏洞。
注册登录可能存在暴力破解、SQL注入、XSS漏洞。
注册一个账号,登录查看是否存在其他的漏洞
在修改用户信息页面发现几个可能存在漏洞的点
用户名更新可能存在SQL注入漏洞、XSS漏洞。
更换头像功能可能存在文件上传漏洞。
修改密码处可能存在SQL注入漏洞
0x2 漏洞检测与利用
使用Seay源代码审计工具检测是否存在漏洞以及存在哪些漏洞
扫描结果
对扫描结果进行整理
可能存在的漏洞:
- SQL注入漏洞
- 文件包含漏洞
- XSS漏洞
- 命令执行漏洞
- 敏感信息泄露漏洞
- 任意文件操作漏洞
- 文件上传漏洞---
2.1 SQL注入漏洞检测
2.1.1 留言处的SQL注入漏洞
在网站评论功能里面发现参数id,此处可能存在SQL注入漏洞
构造poc
?id=1'
页面回显
根据回显结果可知单引号被后端代码过滤了
2.1.1.1 代码审计
查找 messageDetail.php
文件
**后端处理前端传来的参数 id
的过程:先判断是否有GET传递参数 id
,如果有,就对 id
进一步处理,将传递来的id经过 sqlwaf()
函数处理,然后将处理后的id嵌入到sql执行语句中执行。我们要知道此处是否存在 SQL注入漏洞
就要知道 sqlwaf()
函数对传进来的参数 id
做了哪些处理。
在网站文件夹中全局搜索 sqlwaf()
函数
在/sys/lib.php文件中找到了 sqlwaf()
函数
**在 sqlwaf()
函数中使用了正则匹配函数 str_ireplace()
,该函数的特点是不区分大小写。sqlwaf()
函数过滤了很多关键字和特殊符号,由于 str_ireplace()
的原因无法使用大小写绕过,可以利用字符串替换绕过,例如将 and
改为 a||nd
,由于程序是由上至下执行的,所以可以绕过 and
关键字的检测,程序继续执行,正则匹配检测到了 ||
,将 ||
替换为空,所以传到后端的数据就变成了我们想要的 and
关键字,利用这个思路可以替换其它关键字。
2.1.1.2 漏洞检测
**根据sql执行语句可以知道这是一个数字型注入,由此可以构造poc
?id=1 o||rder by 1
····
?id=1 o||rder by 4
?id=1 o||rder by 5
根据 order by
回显结果可以知道有四个回显字段
构造poc查看回显位置
?id=-1 u||nion s||elect 1,2,3,4
构造poc查看数据库中的留言
?id=-1 u||nion s||elect * fr||om comment
可以查询到数据库中的留言
由此可以判断此处存在SQL注入漏洞。
payload
?id=-1 u||nion s||elect *,4 fr||om admin
2.1.2 搜索框处的SQL注入漏洞检测
在搜索框中输入 1'
跳转到了留言处,上面在这里检测出了SQL注入漏洞。
2.1.3 登录处的SQL注入漏洞检测
在登录页面用户框中输入 1'
,在密码框中随便输入一串字符,用BurpSuite抓包,放到Repeater模块中,发送数据包查看响应包
在响应数据包中没有发现有价值的信息
不抓取数据包测试一下,看看页面回显
无论怎么输入,只要用户名或密码不对页面就回显 用户名或密码错误
,在web网页得到有用信息微乎其微,下一步对源码进行审计。
2.1.3.1 代码审计
**在logCheck.php文件中找到SQL语句,根据SQL语句中的变量回溯查找传递进来的参数,分析代码对传递进来的参数做了哪些处理。
**先梳理登陆验证过程,首先 if
语句判断是否有通过POST方式传递进来的参数 submit
、user
、pass
,然后对传递进来的 user
、pass
参数放到 clean_input()
函数中处理,将处理后的参数嵌入到sql语句中,然后执行sql语句在数据库中查询记录,如果数据库中没有记录就输出 用户名或密码错误
,有记录就进入下一个 if
语句中,在第二个 if
语句中通过 get_client_ip()
函数获取 ip
,然后将获取到的 ip
经过 sqlwaf()
函数进行过滤,将过滤后的 ip
嵌入到sql更新语句中并执行sql更新语句。
**全局搜索 clean_input()
函数,在lib.php文件中找到定义的 clean_input()
函数
该函数中使用了 stripslashes()
函数和 mysql_real_escape_string()
函数
*stripslashes()
*函数的作用是删除反斜杠 \
,mysql_real_escape_string()
函数的作用是转义SQL语句中使用的特殊字符,已知mysql_real_escape_string()函数存在宽字节注入漏洞,这里可用宽字节注入漏洞绕过。
**假设第一个sql语句被绕过查询到了数据库中的记录进入到了第二个 if
语句,这里获取 ip
使用到了 get_client_ip()
函数,在lib.php文件中找到了该函数
该函数使用全局变量 $_SERVER
获取 ip
,使用 strcasecmp()
比较函数大小,在虚拟机中测试绕过 strcasecmp()
函数
poc
?a=unkonwn'
在后面随便加一些字符串也可以绕过
**利用这点可以构造以 unknown'
开头的poc注入到请求包的 XFF字段
,继续分析代码,获取 ip
后对 ip
用 sqlwaf()
函数进行了过滤,在上面提到了 sqlwaf()
函数,在这里不再赘述。经过 sqlwaf()
函数后将处理过的参数嵌入到sql更新语句中,执行sql语句。分析了代码执行以及对传递进来的参数的处理流程,可以根据此构造poc。由于sql查询代码没有回显,所以只能借助第二个 if
语句中的sql更新语句执行结果的回显判断是否注入成功。
**检测思路:先在登录表单中传入poc 1%df' union select * from users#
,利用查询到的记录进入第二个 if
语句构造poc检测是否存在 XFF注入
。
第一个数据包的poc
1%df' union select * from users#
第二个数据包的poc
X-Forworded-For: unknown' u||nion s||elect * fr||om users#
2.1.3.2 漏洞检测
第一个数据包
在第二个数据包中添加 XFF
字段
页面回显结果
注入失败,再测试一次,在源码中添加代码输出查询语句以及执行结果,查看未注入成功的原因。
再测试一次
发现宽字节注入没有成功,反斜杠 \
没有被吞掉,猜测应该与编码有关,查看数据库编码。
在config.php文件中发现数据库编码为utf8
**在utf8编码中一个字节表示一个函数,而宽字节注入的条件是在GBK编码下一个汉字用两个字节表示,所以构造的poc并没有绕过 mysql_real_escape_string()
函数,所以这里不存在宽字节注入,由于无法查询到数据所以也就无法进行 XFF注入
,所以这里没有检测出SQL注入漏洞。
补充:
**由于可以更改后台源码,这里将数据库编码设置为gbk以便测试在数据库编码为gbk的情况下是否存在SQL注入漏洞。
用BurpSuite抓包,利用上面的poc测试
第一个数据包
第二个数据包
页面回显
登录成功!!!
**结论:在数据库编码为utf8的情况下不存在SQL注入漏洞,在数据库编码为gbk的情况下存在SQL注入漏洞。
2.1.4 注册处的SQL注入漏洞检测
regCheck.php
由于有 strlen()
函数的存在过滤了长度大于16的传递过来的参数user,在一定程度上限制住了绝大多数恶意sql语句的注入,看看其它参数
**看到两条sql语句,由于对 user
参数的限制不能通过 user
参数传递恶意的sql语句,所以不能借助 select
查询语句进行SQL注入。在第17行代码中发现传递进来的 pass
参数,继续分析代码,在第32中发现被处理的参数 pass
出现在sql语句中,但是由于被当作参数进行执行,无法造成注入漏洞,所以此处不存在SQL注入漏洞。
2.1.5 用户名更新处的SQL注入漏洞检测
在updateName.php文件中查看源码
**这里对传递进来的参数 username
做了长度检测,然后经过 clean_input()
函数的处理,clean_input()
函数在上面已经分析过,这里不再赘述。用正则表达式过滤参数 user
,由于 \w
表示只允许数字、字母、_
、·
,所以无法构造恶意的sql语句,无法利用 select
语句进行SQL注入,在 update
sql语句中除了 $clean_username
之外还有 $_SESSION['user_id']
,由于 $_SESSION['user_id']
不可控,所以无法利用它构造恶意sql语句,这里没有检测到SQL注入漏洞。
2.1.6 修改密码处的SQL注入漏洞检测
分析代码:
**处理参数的过程:首先判断参数 passwd
是否为空,不为空继续执行,用 clean_input()
处理传递进来的参数,函数的作用不再赘述,将处理过的参数嵌入到sql语句中执行。在上面我们知道,在数据库编码为gbk时存在宽字节注入,由于数据库编码为utf8,所以不存在宽字节注入漏洞。即使存在宽字节注入漏洞,该漏洞也无法利用,因为代码中没有对sql语句执行结果的回显,即使恶意的sql查询语句被正常执行,也无法回显出查询结果。
2.1.7 管理员登录处的SQL注入漏洞检测
随便输入一串含有单引号的字符串
页面回显
数据库没有报错,应该是后端屏蔽了数据库报错信息,查看源码。
2.1.7.1 代码审计
**后端代码对通过POST传递过来的参数没有经过任何过滤直接嵌入到了sql查询语句中(声明:添加 stripslashes()
函数是因为通过POST传参之后输出的变量 $name
值中单引号前莫名其妙被添加了反斜杠 \
,查看了php.ini配置文件,GPC为Off,后来问了一些师傅可能是全局变量的原因,然后搜索全局变量也没有找到原因,无奈只能添加一行代码去掉反斜杠继续测试)。
**由于后端代码没有对输入的参数进行任何过滤,这里直接可以构造万能密码登录。
payload:
admin ' or '1'='1'#
2.1.7.2 漏洞检测
执行结果
登录成功!!!
所以在此处检测出SQL注入漏洞。
2.1.8 二次截断注入漏洞
危险文件在messageSub.php文件中
在拼接SQL语句之前有clean_input()函数过滤
clean_input()函数中有两个函数,stripslashes() 函数删除反斜杠,mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
$clean_message的值通过POST传参传递进来,然后经过clean_input函数过滤,最终赋值给$clean_message变量
$_SESSION['username']来自logCheck.php在用户登陆时从数据库中获取
所以要构造payload需要从用户名入手
在用户注册时使用了clean_input函数
当输入用户名为xxx\的时候,被转义成xxx**
转义相关处理代码在lib.php中
本地测试
这样处理可以转义相关的特殊字符,这种防护相当于GPC是永远打开的。
传递进来的参数被转义成了xxx\,然后经过clean_input的stripslashes变成xxx\,再经过clean_input的mysql_real_escape_string又变成xxx\,这是前面的\转义了后面的\,所以现在我们的用户名在数据库中就是xxx\。
可以利用\进行转义,在用户注册时构造恶意的用户名用于单引号转义,然后在用户留言处进行SQL语句拼接。
最终构造的payload为
username: xxx\
comment: ,(select @@datadir),now());#
最终拼接的SQL语句为
INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('xxx\',',(select @@datadir),now());#',now())
简化就是
INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('xxx\',',(select @@datadir),now());
查出数据库路径!
2.1.9 其它的SQL注入漏洞检测
**搜索select、update、insert、delete等与sql语句相关的关键字查询剩余可能存在SQL注入漏洞的点,在管理员对普通用户、评论等管理处都发现了sql语句,但是由于传递进去的参数都使用了 clean_input()
函数过滤,而数据库编码为 utf8
,所以无法造成SQL注入漏洞,所以利用 clean_input()
函数过滤传递进来的参数的地方均没有SQL注入漏洞。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论