记一次对VAuditDemo平台的代码审计(上)

admin 2022年4月16日01:24:48SecIN安全技术社区记一次对VAuditDemo平台的代码审计(上)已关闭评论29 views5304字阅读17分40秒阅读模式

0x0 前言

搭建平台使用的架构是WAMP架构

操作系统为windows7

Apache版本为2.4.39

MySQL版本为8.0.12

PHP版本为5.2.17

0x1 信息收集

1.1 探测可能存在的漏洞类型

打开网站发现几个值得关注的功能,评论留言,搜索框,注册登录功能。

猜测可能存在的漏洞:

评论留言可能存在SQL注入、XSS漏洞。

搜索框可能存在SQL注入、XSS漏洞、命令执行漏洞。

注册登录可能存在暴力破解、SQL注入、XSS漏洞。

注册一个账号,登录查看是否存在其他的漏洞

记一次对VAuditDemo平台的代码审计(上)

在修改用户信息页面发现几个可能存在漏洞的点

用户名更新可能存在SQL注入漏洞、XSS漏洞。

更换头像功能可能存在文件上传漏洞。

修改密码处可能存在SQL注入漏洞

0x2 漏洞检测与利用

使用Seay源代码审计工具检测是否存在漏洞以及存在哪些漏洞

扫描结果

记一次对VAuditDemo平台的代码审计(上)

对扫描结果进行整理

可能存在的漏洞:

  1. SQL注入漏洞
  2. 文件包含漏洞
  3. XSS漏洞
  4. 命令执行漏洞
  5. 敏感信息泄露漏洞
  6. 任意文件操作漏洞
  7. 文件上传漏洞---

2.1 SQL注入漏洞检测

2.1.1 留言处的SQL注入漏洞

在网站评论功能里面发现参数id,此处可能存在SQL注入漏洞

记一次对VAuditDemo平台的代码审计(上)

构造poc

?id=1'

页面回显

记一次对VAuditDemo平台的代码审计(上)

根据回显结果可知单引号被后端代码过滤了

2.1.1.1 代码审计

查找 messageDetail.php文件

记一次对VAuditDemo平台的代码审计(上)

**后端处理前端传来的参数 id的过程:先判断是否有GET传递参数 id,如果有,就对 id进一步处理,将传递来的id经过 sqlwaf()函数处理,然后将处理后的id嵌入到sql执行语句中执行。我们要知道此处是否存在 SQL注入漏洞就要知道 sqlwaf()函数对传进来的参数 id做了哪些处理。

在网站文件夹中全局搜索 sqlwaf()函数

记一次对VAuditDemo平台的代码审计(上)

在/sys/lib.php文件中找到了 sqlwaf()函数

记一次对VAuditDemo平台的代码审计(上)

**在 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

记一次对VAuditDemo平台的代码审计(上)

根据 order by回显结果可以知道有四个回显字段

构造poc查看回显位置

?id=-1 u||nion s||elect 1,2,3,4

记一次对VAuditDemo平台的代码审计(上)

构造poc查看数据库中的留言

?id=-1 u||nion s||elect * fr||om comment

可以查询到数据库中的留言

记一次对VAuditDemo平台的代码审计(上)

由此可以判断此处存在SQL注入漏洞。

payload

?id=-1 u||nion s||elect *,4 fr||om admin

记一次对VAuditDemo平台的代码审计(上)

2.1.2 搜索框处的SQL注入漏洞检测

在搜索框中输入 1'跳转到了留言处,上面在这里检测出了SQL注入漏洞。

2.1.3 登录处的SQL注入漏洞检测

在登录页面用户框中输入 1',在密码框中随便输入一串字符,用BurpSuite抓包,放到Repeater模块中,发送数据包查看响应包

记一次对VAuditDemo平台的代码审计(上)

在响应数据包中没有发现有价值的信息

不抓取数据包测试一下,看看页面回显

记一次对VAuditDemo平台的代码审计(上)

无论怎么输入,只要用户名或密码不对页面就回显 用户名或密码错误,在web网页得到有用信息微乎其微,下一步对源码进行审计。

2.1.3.1 代码审计

**在logCheck.php文件中找到SQL语句,根据SQL语句中的变量回溯查找传递进来的参数,分析代码对传递进来的参数做了哪些处理。

记一次对VAuditDemo平台的代码审计(上)

**先梳理登陆验证过程,首先 if语句判断是否有通过POST方式传递进来的参数 submituserpass,然后对传递进来的 userpass参数放到 clean_input()函数中处理,将处理后的参数嵌入到sql语句中,然后执行sql语句在数据库中查询记录,如果数据库中没有记录就输出 用户名或密码错误,有记录就进入下一个 if语句中,在第二个 if语句中通过 get_client_ip()函数获取 ip,然后将获取到的 ip经过 sqlwaf()函数进行过滤,将过滤后的 ip嵌入到sql更新语句中并执行sql更新语句。

**全局搜索 clean_input()函数,在lib.php文件中找到定义的 clean_input()函数

记一次对VAuditDemo平台的代码审计(上)

该函数中使用了 stripslashes()函数和 mysql_real_escape_string()函数

*stripslashes()*函数的作用是删除反斜杠 \mysql_real_escape_string()函数的作用是转义SQL语句中使用的特殊字符,已知mysql_real_escape_string()函数存在宽字节注入漏洞,这里可用宽字节注入漏洞绕过。

**假设第一个sql语句被绕过查询到了数据库中的记录进入到了第二个 if语句,这里获取 ip使用到了 get_client_ip()函数,在lib.php文件中找到了该函数

记一次对VAuditDemo平台的代码审计(上)

该函数使用全局变量 $_SERVER获取 ip,使用 strcasecmp()比较函数大小,在虚拟机中测试绕过 strcasecmp()函数

poc

?a=unkonwn'

记一次对VAuditDemo平台的代码审计(上)

在后面随便加一些字符串也可以绕过

记一次对VAuditDemo平台的代码审计(上)

**利用这点可以构造以 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 漏洞检测

第一个数据包

记一次对VAuditDemo平台的代码审计(上)

在第二个数据包中添加 XFF字段

记一次对VAuditDemo平台的代码审计(上)

页面回显结果

记一次对VAuditDemo平台的代码审计(上)

注入失败,再测试一次,在源码中添加代码输出查询语句以及执行结果,查看未注入成功的原因。

记一次对VAuditDemo平台的代码审计(上)

记一次对VAuditDemo平台的代码审计(上)

再测试一次

记一次对VAuditDemo平台的代码审计(上)

发现宽字节注入没有成功,反斜杠 \没有被吞掉,猜测应该与编码有关,查看数据库编码。

在config.php文件中发现数据库编码为utf8

记一次对VAuditDemo平台的代码审计(上)

**在utf8编码中一个字节表示一个函数,而宽字节注入的条件是在GBK编码下一个汉字用两个字节表示,所以构造的poc并没有绕过 mysql_real_escape_string()函数,所以这里不存在宽字节注入,由于无法查询到数据所以也就无法进行 XFF注入,所以这里没有检测出SQL注入漏洞。

补充:

**由于可以更改后台源码,这里将数据库编码设置为gbk以便测试在数据库编码为gbk的情况下是否存在SQL注入漏洞。

记一次对VAuditDemo平台的代码审计(上)

用BurpSuite抓包,利用上面的poc测试

第一个数据包

记一次对VAuditDemo平台的代码审计(上)

第二个数据包

记一次对VAuditDemo平台的代码审计(上)

页面回显

记一次对VAuditDemo平台的代码审计(上)

登录成功!!!

**结论:在数据库编码为utf8的情况下不存在SQL注入漏洞,在数据库编码为gbk的情况下存在SQL注入漏洞。

2.1.4 注册处的SQL注入漏洞检测

regCheck.php

记一次对VAuditDemo平台的代码审计(上)

由于有 strlen()函数的存在过滤了长度大于16的传递过来的参数user,在一定程度上限制住了绝大多数恶意sql语句的注入,看看其它参数

记一次对VAuditDemo平台的代码审计(上)

**看到两条sql语句,由于对 user参数的限制不能通过 user参数传递恶意的sql语句,所以不能借助 select查询语句进行SQL注入。在第17行代码中发现传递进来的 pass参数,继续分析代码,在第32中发现被处理的参数 pass出现在sql语句中,但是由于被当作参数进行执行,无法造成注入漏洞,所以此处不存在SQL注入漏洞。

2.1.5 用户名更新处的SQL注入漏洞检测

在updateName.php文件中查看源码

记一次对VAuditDemo平台的代码审计(上)

**这里对传递进来的参数 username做了长度检测,然后经过 clean_input()函数的处理,clean_input()函数在上面已经分析过,这里不再赘述。用正则表达式过滤参数 user,由于 \w表示只允许数字、字母、_·,所以无法构造恶意的sql语句,无法利用 select语句进行SQL注入,在 updatesql语句中除了 $clean_username之外还有 $_SESSION['user_id'],由于 $_SESSION['user_id']不可控,所以无法利用它构造恶意sql语句,这里没有检测到SQL注入漏洞。

2.1.6 修改密码处的SQL注入漏洞检测

记一次对VAuditDemo平台的代码审计(上)

分析代码:

**处理参数的过程:首先判断参数 passwd是否为空,不为空继续执行,用 clean_input()处理传递进来的参数,函数的作用不再赘述,将处理过的参数嵌入到sql语句中执行。在上面我们知道,在数据库编码为gbk时存在宽字节注入,由于数据库编码为utf8,所以不存在宽字节注入漏洞。即使存在宽字节注入漏洞,该漏洞也无法利用,因为代码中没有对sql语句执行结果的回显,即使恶意的sql查询语句被正常执行,也无法回显出查询结果。

2.1.7 管理员登录处的SQL注入漏洞检测

随便输入一串含有单引号的字符串

记一次对VAuditDemo平台的代码审计(上)

页面回显

记一次对VAuditDemo平台的代码审计(上)

数据库没有报错,应该是后端屏蔽了数据库报错信息,查看源码。

2.1.7.1 代码审计

记一次对VAuditDemo平台的代码审计(上)

**后端代码对通过POST传递过来的参数没有经过任何过滤直接嵌入到了sql查询语句中(声明:添加 stripslashes()函数是因为通过POST传参之后输出的变量 $name值中单引号前莫名其妙被添加了反斜杠 \,查看了php.ini配置文件,GPC为Off,后来问了一些师傅可能是全局变量的原因,然后搜索全局变量也没有找到原因,无奈只能添加一行代码去掉反斜杠继续测试)。

**由于后端代码没有对输入的参数进行任何过滤,这里直接可以构造万能密码登录。

payload:

admin ' or '1'='1'#

2.1.7.2 漏洞检测

记一次对VAuditDemo平台的代码审计(上)

执行结果

记一次对VAuditDemo平台的代码审计(上)

登录成功!!!

所以在此处检测出SQL注入漏洞。

2.1.8 二次截断注入漏洞

危险文件在messageSub.php文件中

记一次对VAuditDemo平台的代码审计(上)

在拼接SQL语句之前有clean_input()函数过滤

记一次对VAuditDemo平台的代码审计(上)

clean_input()函数中有两个函数,stripslashes() 函数删除反斜杠,mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。

$clean_message的值通过POST传参传递进来,然后经过clean_input函数过滤,最终赋值给$clean_message变量

记一次对VAuditDemo平台的代码审计(上)

$_SESSION['username']来自logCheck.php在用户登陆时从数据库中获取

记一次对VAuditDemo平台的代码审计(上)

所以要构造payload需要从用户名入手

在用户注册时使用了clean_input函数

记一次对VAuditDemo平台的代码审计(上)

当输入用户名为xxx\的时候,被转义成xxx**

转义相关处理代码在lib.php中

记一次对VAuditDemo平台的代码审计(上)

本地测试

记一次对VAuditDemo平台的代码审计(上)

这样处理可以转义相关的特殊字符,这种防护相当于GPC是永远打开的。

传递进来的参数被转义成了xxx\,然后经过clean_input的stripslashes变成xxx\,再经过clean_input的mysql_real_escape_string又变成xxx\,这是前面的\转义了后面的\,所以现在我们的用户名在数据库中就是xxx\。

记一次对VAuditDemo平台的代码审计(上)

可以利用\进行转义,在用户注册时构造恶意的用户名用于单引号转义,然后在用户留言处进行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());

记一次对VAuditDemo平台的代码审计(上)

查出数据库路径!

2.1.9 其它的SQL注入漏洞检测

**搜索select、update、insert、delete等与sql语句相关的关键字查询剩余可能存在SQL注入漏洞的点,在管理员对普通用户、评论等管理处都发现了sql语句,但是由于传递进去的参数都使用了 clean_input()函数过滤,而数据库编码为 utf8,所以无法造成SQL注入漏洞,所以利用 clean_input()函数过滤传递进来的参数的地方均没有SQL注入漏洞。

记一次对VAuditDemo平台的代码审计(上)

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月16日01:24:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  记一次对VAuditDemo平台的代码审计(上) http://cn-sec.com/archives/916982.html