问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
【PHP代码审计】Atutor2.2.4 CVE全复现
渗透测试
ATutor是一个开源基于Web的学习管理系统,2.2.4是目前的最新版本,我汇总了所有CVE进行复现,对国外站点PHP代码审计的学习有所帮助。
ATutor是一个开源基于Web的学习管理系统(LCMS),2.2.4是目前的最新版本,我汇总了所有CVE进行复现,进行黑白盒测试,对国外站点PHP代码审计的学习有所帮助。 1. [CVE-2019-11446](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11446) ---------------------------------------------------------------------------------- 任意文件上传 利用条件 l 获得一个有教师权限的用户(即可以创建和管理课程) l 版本为2.2.4 利用教师用户新建一个课程  进入课程,找到文件管理界面  这里是上传点,存在任意文件上传漏洞,原因是后端采用后缀名黑名单过滤,过滤不严谨,可以修改后缀名为phP,或者phtml进行绕过 通过burpsuite进行抓包,发现上传点为mods/\_core/file\_manager/upload.php  因此,我们对mods/\_core/file\_manager/upload.php进行审计  这是一个常规的文件上传代码,重点看处理过滤的部分,代码中对上传的文件有两处过滤 1\. 一个是对文件名进行str\_replace函数过滤,处理掉了文件名中的特殊字符,这个无所谓 2\. 另一个对文件后缀名的变量$ext,进行in\_array函数黑名单判断,检测是否包含非法的后缀名,其中,$IllegalExtentions变量是后缀的黑名单  我们全局搜索下$IllegalExtentions变量具体的值   我写了一个demo,来测试in\_array是否大小写敏感  经过测试,该黑名单只对小写进行过滤,因此可以大小写转换phP,进行绕过,同时黑名单过滤不严谨,用php其他可以被解析的后缀也可以绕过,以下是PHP其他的后缀名:.php3 .php4 .php5 .php7 .php8 .pht .phar .phpt .pgif .phtml .phtm 将webshell上传成功后,怎么知道文件的位置在哪里呢?  通过审计,可以知道,文件被move\_uploaded\_file函数上传到了 $path.$\_FILES\['uploadedfile'\]\['name'\],其中“.”是PHP中的拼接符号,前面的$path变量是目录的值,后面的$\_FILES\['uploadedfile'\]\['name'\]其实就是文件名的值  我们跟进下,$path的值具体是什么  由此可知,$path的值是由AT\_CONTENT\_DIR和$\_SESSION\['course\_id'\]以及$\_POST\['pathext'\]这三个值拼接成的,我们一个个来找 看了下我们post的请求,pathext是为空的 AT\_CONTENT\_DIR中,目录位置为atutor/content,前面的是它的WEB目录绝对路径  course\_id的值在自定义函数add\_update\_course中  因为add\_update\_course函数最后会返回course\_id的值,所以我们只用全局搜索哪个页面调用了该函数就行了  mods\_core\\courses\\users\\create\_course.php页面调用了该函数,并将函数返回的值,赋给了$errors变量,因为course\_id是一个大于0的整数,所以$errors的if判断肯定是为true的,即$errors!=False,最后将$errors(也就是course\_id的值)通过header响应头的Location字段(即重定向的URL)输出,所以这里我们需要通过burpsuite抓包,将其放入repeater模块中,查看响应包的Location字段  回到开头,我们利用教师用户新建一个课程  通过burpsuite抓包,发现返回了course\_id  大功告成,文件上传位置变量$path的值是由AT\_CONTENT\_DIR和$\_SESSION\['course\_id'\]以及$\_POST\['pathext'\]这三个值拼接成的,因为AT\_CONTENT\_DIR为atutor/content,$\_SESSION\['course\_id'\]为2,$\_POST\['pathext'\]为空,所以上传位置在 <http://xx.com/atutor/content/2/xx.php>  2. [CVE-2019-12169](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12169) ---------------------------------------------------------------------------------- 任意文件上传 利用条件 l 获得管理员权限用户 l 版本为2.2.4 漏洞的位置在mods/\_core/languages/language\_import.php,访问要先登录管理员权限用户,其他普通用户打不开  这里又是一个上传点,通过burpsuite进行抓包,发现上传点依然是language\_import.php  我们对mods/\_core/languages/language\_import.php进行审计  我们上传的文件会传到$languageManager这个类的import函数里面 因为language\_import.php包含了vitals.inc.php文件,所以$languageManager变量在vitals.inc.php里,可以看到变量$languageManager就是类LanguageManager   我们再跟进LanguageManager类的import函数  重点看$archive = new PclZip($filename); 其中PclZip是一个对压缩包进行处理的类,$filename是我们在函数中传进来的参数,所以说我们上传的文件必须是一个压缩包  可以看到,后面$archive->extract( PCLZIP\_OPT\_PATH, $import\_path),即我们上传的文件被解压到了$import\_path变量(应该是一个目录的地址) 我们上下文找下$import\_path变量的值,发现其值是AT\_CONTENT\_DIR .和'import/'拼接起来的, AT\_CONTENT\_DIR中,目录位置为atutor/content,前面的是它的WEB目录绝对路径,所以$import\_path的值应该为atutor/content/import,即上传文件的目录   我们将poc.php文件,进行zip压缩后,将压缩包上传  访问上文中我们总结出来的上传目录atutor/content/import 即http://xx.com/atutor/content/import/poc.php  3. [CVE-2021-43498](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-43498) ---------------------------------------------------------------------------------- 访问控制缺陷(导致可修改任意用户密码) 利用条件 l 版本为2.2.4 存在漏洞的地方在password\_reminder.php,但是要携带特定的参数才能触发漏洞  我们先审计下password\_reminder.php,进入到密码找回的判断逻辑 密码找回是会发送个链接到你用户绑定的邮箱的,我们触发漏洞的参数,就是去猜测找回密码的链接的参数的值,所以必须要代码审计  首先要设置参数id、g、h,才能进入if判断里面,其中参数id就是用户的id值,参数g是密码找回发送链接到你邮箱的时间,参数h是sha1(参数id+参数g+用户的密码md5),计算出sha1后,再取其从第五个数开始的后十五位 上面看不懂也没关系,我们一步步来,变量$current = intval(((time()/60)/60)/24);我用本地PHP环境跑了一下,得到变量$current当前的值为19524  $expiry\_date = $\_REQUEST\['g'\] + AT\_PASSWORD\_REMINDER\_EXPIRY; 其中AT\_PASSWORD\_REMINDER\_EXPIRY是常量,值为2,$expiry\_date=19524+2,就是19526 参数g的值则为19524 if ($current > $expiry\_date),就会exit退出,所以$expiry\_date要大于$current $row = queryDB($sql, array(TABLE\_PREFIX, $\_REQUEST\['id'\]), TRUE); 为了确保用户是存在的,我们将参数id暂时设为1 if ($\_REQUEST\['h'\] !== $hash\_bit),就会报错,所以参数h的值必须要等于变量$hash\_bit,其中上文提到,参数h是sha1(参数id+参数g+用户的密码md5怎么办? 先看一下数据库中用户1的password字段为8635fc开头  还是老样子,我们在本地环境跑一下,看看参数id+参数g+用户的密码md5算出来是多少   最终算出来为28160,为什么?因为在PHP中,整数和字符串进行运算,字符串若前面为字母,则取值为0,若字符串前面为数字,以这里密码md5的8635fc为例,则取字母前面的数字为值,所以说1(参数id的值)+19524(参数g的值)+8635(用户密码md5)=28160 但是我们也说了,参数h是sha1(参数id+参数g+用户的密码md5),计算出sha1后,再取其从第五个数开始的后十五位,所以得用脚本生成一个经过sha1和substr函数运算后的字典,再用burpsuite的intruder模块进行爆破(因为我们无法知道用户密码md5开头的值)  我这里是用PHP生成了一个字典,保存为h.txt  上面的字典,是爆破我们参数h的值 但是我们依然没有重置用户密码,还需要参数form\_password\_hidden和 form\_change,所以还没有代码审计完  我们需要设置一个参数form\_change,进入if判断,值为空就可以 我们的目的是进入if (!$msg->containsErrors()),里面可以执行update用户密码的SQL语句 关于!$msg->containsErrors(),要求前面参数id,g,h的值设置正确,就不会报错,ok,如果以上都理解了,我们就可以执行攻击了 参数form\_password\_hidden是重新设置的新密码,一般是md5,但是为了方便大家看懂,我这里的值直接设置为yyds,以显示我们攻击成功了,我们直接通过burpsuite的intrude模块进行爆破  我这里是成功了的,注意发包的时候,同个payload有时返回200有时候302,所以最好多尝试几次,响应的字段长度基本差不了多少,所以不是基于响应长度判断是否成功,我这里通过爆破成功修改了用户密码  4. [CVE-2020-23341](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-23341) ---------------------------------------------------------------------------------- 反射型XSS 利用条件 l 版本为2.2.4 漏洞存在的位置在themes\\default\\include\\header.tmpl.php  注意前面的if判断,页面中必须要定义了AT\_INCLUDE\_PATH常量,否则就exit退出,但是这个header.tmpl.php是不包含此常量的,也就是说它需要被其他文件包含(通过.tmpl.php的命名我们就可以知道这是一个模板文件) 我们来全局搜索下,哪些文件是包含了header.tmpl.php的,发现header.inc.php文件是包含的,但是header.inc.php又没有定义AT\_INCLUDE\_PATH常量,所以我们需要套娃,找到包含header.inc.php的文件  继续搜索,哪些文件是包含了header.inc.php的,发现about.php包含,而且定义了AT\_INCLUDE\_PATH常量,所以我们从about.php页面入手  Ok,找到要执行攻击的页面了,但是漏洞在哪里呢? 我们前文说过漏洞存在的位置在themes\\default\\include\\header.tmpl.php 所以继续往下进行代码审计,一般反射型XSS肯定都是靠参数传递的啦,我们直接在该页面搜”$\_”关键字,找到$\_GET\[‘fb’\];  发现printNoLookupFeedback函数会将我们传的参数显示出来,这里有戏,但是我们要跟进函数,看看会不会过滤尖括号   这里又套娃了,刚刚的$msg->xx()是类中的一个函数,这里的$this->savant->xx()也是类中的函数,继续跟进吧  通过全局搜索可以知道,函数属于Savant2这个类,它是先把类Savant2的实例化(new Savant2 ())赋值给变量$ Savant,再将变量传参给类Message的实例化,即new Message($ Savant),类Message再通过构造函数,将传进来的值,赋给$this-> savant  看完了,这个传参点是没有过滤的,我们直接通过about.php页面执行XSS payload吧  5. [CVE-2019-7172](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-7172) -------------------------------------------------------------------------------- 储存型XSS 利用条件 l 获得管理员权限的用户 l 版本为2.2.4 先登录管理员用户,再打开mods/\_core/users/admins/my\_edit.php页面,在real\_name位置提交XSS payload  保存后,打开mods/\_core/users/admins/index.php页面,发现执行成功  漏洞出在mods/\_core/users/admins/my\_edit.php,我们对其进行审计  $msg->containsErrors()默认是false,所以负负得正,为true,进入if里面 其中,$addslashes会对我们提交的real\_name值进行过滤,我们先看看$addslashes被赋了哪个过滤函数  $addslashes其实就是mysql\_real\_escape\_string函数  过滤的无非是斜杠、单引号、双引号、回车这些,和尖括号无关,所以对XSS攻击是没有过滤的,除非你是通过标签的属性,即闭合双引号来XSS 6. [CVE-2019-16114](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16114) ---------------------------------------------------------------------------------- 变量覆盖 我的理解是,因为在安装WEB的时候,跳过了步骤5,即数据库配置这一块,导致安装的页面依然可以访问,二次安装,篡改数据库的配置,不过这个确实没想到,算是拓展下思路
发表于 2024-03-04 09:00:01
阅读 ( 5222 )
分类:
代码审计
0 推荐
收藏
0 条评论
请先
登录
后评论
pokeroot
6 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!