记一次简单的源码审计流程,审计方法参考先前博客:
phpstorm + phpstudy 进行php项目调试和调试时超出连接时长500问题_phpstudy接口请求超时-优快云博客
存储型XSS——/monstra-3.0.4/users/1/edit
漏洞复现
注册用户并登录,
获取Cookie: _ga=GA1.1.696573224.1717850752; XDEBUG_SESSION=XDEBUG_ECLIPSE; PHPSESSID=0c26ifno9mng4dsc3h99f8qnf2; _gid=GA1.1.1605504635.1718256879
,点击Edit profile进入/monstra-3.0.4/users/1/edit
在About Me字段输入payload:</textarea><script>alert(1)</script>
点击Save后,payload通过post方法发送给服务器
再次点击Edit profile进入/monstra-3.0.4/users/5/edit,返回页面就成功把payload显示到前端about_me字段
上述图片可以看到触发了XSS
该xss为存储型xss漏洞,刚刚输入的payload会存储在本地数据库\monstra-3.0.4\storage\database\users.table.xml中,以下是数据库中对应的内容
漏洞成因:
对于用户输入的数据</textarea><script>alert(1)</script>,
虽然经过htmlspecialchars()函数转义特殊字符”<”,”>”为< >后
再存储 </textarea><script>alert(1)</script>
但是当网页再次通过以下方式读取时:
$xml = file_get_contents($file); $data = simplexml_load_string($xml);
$data->xpath()
会将数据库中原本已经成功转义在存储的特殊字符重新变回原本的”<”和”>”
从而导致xss漏洞产生
下面是源码调试过程:
Xss触发路径为/monstra-3.0.4/users/5/edit,
该路径对应的php文件:monstra-3.0.4/plugins/box/users/views/frontend/edit.view.php
edit.view.php文件第40行,调用echo方法直接输出$user数组变量中的’about_me’对应的value值;
而Array类型变量$user在edit.view.php的父文件users.admin.php中第114行定义,如下图
这一行代码中$users变量通过select方法,查询数据库中user_id对于的数据并通过Array的形式返回给先前提到的$user变量。
$user变量在users.admin.php中第22行定义,是一个Table类
Table类在monstra-3.0.4/engine/Xmldb/Table.php文件中被定义
在Table.php文件中第444行定义select方法,其中在454行调用xpath方法来对xml类型的数据库对象进行数据查询,并接受返回值
这个xml_object是Table类实例化时调用__constract()方法给实例的内置Array类型变量table所绑定的key,它在创建实例时赋初值,是SimpleXMLElement类型对象。对应函数参考下图:
可以发现其中的XML::loadFile方法就是返回’xml_object’对应的value取值
而在XML.php文件中的loadFile方法,最关键的两条函数便是
$xml = file_get_contents($file); $data = simplexml_load_string($xml);
最终return $data就是返回了SimpleXMLElement类型对象
补充payload存储时经过:
Payload在存储时会经过如下函数,被htmlspecialchar()转义特殊字符
总结:
当用户输入payload,存储进数据库后,再次访问/monstra-3.0.4/users/5/edit时,会因为执行echo $user[‘about_me’]实现xss,这个$user的值是通过Table类的select方法:识别user_id拼接入xpath定位方法,查询对应数据库中的值并返回,生成SimpleXMLElement类型对象,再把SimpleXMLElement对象转换为对应Array类型对象然后retutn,最终赋值给$user[‘about_me’]变量。虽然在用户写入payload时,会通过htmlspecialchars()函数转义特殊字符,当在读取数据时——“生成SimpleXMLElement类型对象”这一步会导致先前被转义字符变回原本字符形式,最终导致存储型xss漏洞。