首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >此PHP代码中是否存在任何安全漏洞?

此PHP代码中是否存在任何安全漏洞?
EN

Stack Overflow用户
提问于 2010-03-29 20:57:07
回答 2查看 3.3K关注 0票数 14

我刚刚有一个网站要管理,但我不太确定的代码,前面的家伙写的。我正在粘贴下面的登录过程,您能看一下并告诉我是否存在安全漏洞吗?乍一看,人们似乎可以通过SQL注入或操作cookie和?m=参数进入其中。

代码语言:javascript
复制
define ( 'CURRENT_TIME', time ()); / / Current time. 
define ( 'ONLINE_TIME_MIN', (CURRENT_TIME - BOTNET_TIMEOUT)); / / Minimum time for the status of "Online". 
define ( 'DEFAULT_LANGUAGE', 'en'); / / Default language. 
define ( 'THEME_PATH', 'theme'); / / folder for the theme. 

/ / HTTP requests. 
define ( 'QUERY_SCRIPT', basename ($ _SERVER [ 'PHP_SELF'])); 
define ( 'QUERY_SCRIPT_HTML', QUERY_SCRIPT); 
define ( 'QUERY_VAR_MODULE', 'm'); / / variable contains the current module. 
define ( 'QUERY_STRING_BLANK', QUERY_SCRIPT. '? m ='); / / An empty query string. 
define ( 'QUERY_STRING_BLANK_HTML', QUERY_SCRIPT_HTML. '? m ='); / / Empty query string in HTML. 
define ( 'CP_HTTP_ROOT', str_replace ( '\ \', '/', (! empty ($ _SERVER [ 'SCRIPT_NAME'])? dirname ($ _SERVER [ 'SCRIPT_NAME']):'/'))); / / root of CP. 

/ / The session cookie. 
define ( 'COOKIE_USER', 'p'); / / Username in the cookies. 
define ( 'COOKIE_PASS', 'u'); / / user password in the cookies. 
define ( 'COOKIE_LIVETIME', CURRENT_TIME + 2592000) / / Lifetime cookies. 
define ( 'COOKIE_SESSION', 'ref'); / / variable to store the session. 
define ( 'SESSION_LIVETIME', CURRENT_TIME + 1300) / / Lifetime of the session. 

////////////////////////////////////////////////// ///////////////////////////// 
/ / Initialize. 
////////////////////////////////////////////////// ///////////////////////////// 

/ / Connect to the database. 
if (! ConnectToDB ()) die (mysql_error_ex ()); 

/ / Connecting topic. 
require_once (THEME_PATH. '/ index.php'); 

/ / Manage login. 
if (! empty ($ _GET [QUERY_VAR_MODULE])) 
( 
  / / Login form. 
  if (strcmp ($ _GET [QUERY_VAR_MODULE], 'login') === 0) 
  ( 
    UnlockSessionAndDestroyAllCokies (); 
     
    if (isset ($ _POST [ 'user']) & & isset ($ _POST [ 'pass'])) 
    ( 
      $ user = $ _POST [ 'user']; 
      $ pass = md5 ($ _POST [ 'pass']); 
     
      / / Check login. 
      if (@ mysql_query ( "SELECT id FROM cp_users WHERE name = '". addslashes ($ user). "' AND pass = '". addslashes ($ pass). "' AND flag_enabled = '1 'LIMIT 1") & & @ mysql_affected_rows () == 1) 
      ( 
        if (isset ($ _POST [ 'remember']) & & $ _POST [ 'remember'] == 1) 
        ( 
          setcookie (COOKIE_USER, md5 ($ user), COOKIE_LIVETIME, CP_HTTP_ROOT); 
          setcookie (COOKIE_PASS, $ pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 
        ) 
     
        LockSession (); 
        $ _SESSION [ 'Name'] = $ user; 
        $ _SESSION [ 'Pass'] = $ pass; 
        / / UnlockSession (); 
       
        header ( 'Location:'. QUERY_STRING_BLANK. 'home'); 
      ) 
      else ShowLoginForm (true); 
      die (); 
    ) 
     
    ShowLoginForm (false); 
    die (); 
  ) 
   
  / / Output 
  if (strcmp ($ _GET [ 'm'], 'logout') === 0) 
  ( 
    UnlockSessionAndDestroyAllCokies (); 
    header ( 'Location:'. QUERY_STRING_BLANK. 'login'); 
    die (); 
  ) 
) 

////////////////////////////////////////////////// ///////////////////////////// 
/ / Check the login data. 
////////////////////////////////////////////////// ///////////////////////////// 

$ logined = 0, / / flag means, we zalogininy. 

/ / Log in session. 
LockSession (); 
if (! empty ($ _SESSION [ 'name']) & &! empty ($ _SESSION [ 'pass'])) 
( 
  if (($ r = @ mysql_query ( "SELECT * FROM cp_users WHERE name = '". addslashes ($ _SESSION [' name'])."' AND pass = ' ". addslashes ($ _SESSION [' pass']). " 'AND flag_enabled = '1' LIMIT 1 ")))$ logined = @ mysql_affected_rows (); 
) 
/ / Login through cookies. 
if ($ logined! == 1 & &! empty ($ _COOKIE [COOKIE_USER]) & &! empty ($ _COOKIE [COOKIE_PASS])) 
( 
  if (($ r = @ mysql_query ( "SELECT * FROM cp_users WHERE MD5 (name )='". addslashes ($ _COOKIE [COOKIE_USER ])."' AND pass = '". addslashes ($ _COOKIE [COOKIE_PASS]). " 'AND flag_enabled = '1' LIMIT 1 ")))$ logined = @ mysql_affected_rows (); 
) 
/ / Unable to login. 
if ($ logined! == 1) 
( 
  UnlockSessionAndDestroyAllCokies (); 
  header ( 'Location:'. QUERY_STRING_BLANK. 'login'); 
  die (); 
) 

/ / Get the user data. 
$ _USER_DATA = @ Mysql_fetch_assoc ($ r); 
if ($ _USER_DATA === false) die (mysql_error_ex ()); 
$ _SESSION [ 'Name'] = $ _USER_DATA [ 'name']; 
$ _SESSION [ 'Pass'] = $ _USER_DATA [ 'pass']; 

/ / Connecting language. 
if (@ strlen ($ _USER_DATA [ 'language'])! = 2 | |! SafePath ($ _USER_DATA [ 'language']) | |! file_exists ( 'system / lng .'.$_ USER_DATA [' language '].' . php'))$_ USER_DATA [ 'language'] = DEFAULT_LANGUAGE; 
require_once ( 'system / lng .'.$_ USER_DATA [' language'].'. php '); 

UnlockSession (); 
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-29 21:08:02

是的,这段代码中有一些漏洞。

这可能是一个潜在的问题:

代码语言:javascript
复制
define ( 'QUERY_SCRIPT', basename ($ _SERVER [ 'PHP_SELF'])); 

PHP_SELF是坏的,因为攻击者可以控制这个变量。例如,当您使用这个url:http://localhost/index.php/test/junk/hacked访问脚本时,尝试打印PHP_SELF。尽量避免这个变量,如果您确实使用它,请确保您对它进行消毒。在使用此变量时,经常会看到XSS出现。

第一种脆弱性:

代码语言:javascript
复制
setcookie (COOKIE_USER, md5 ($ user), COOKIE_LIVETIME, CP_HTTP_ROOT); 
setcookie (COOKIE_PASS, $ pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 

这是一个相当严重的弱点。如果攻击者在您的应用程序中注入了SQL,那么他们可以立即获得md5哈希和用户名并登录,而不必破坏md5()哈希。就好像你在用明文存储密码一样。

这个会话漏洞是双重的,它也是一个“不朽会话”,会话id的值必须总是大的随机产生的值过期。如果它们不过期,那么它们就更容易使用武力。

您应该永远不要重新发明方向盘,在应用程序一开始就调用session_start(),这将自动生成一个过期的安全会话id。然后使用像$_SESSION['user']这样的会话变量来跟踪浏览器是否实际登录。

第二种脆弱性:

代码语言:javascript
复制
$ pass = md5 ($ _POST [ 'pass']);

md5()被证明是不安全的,因为冲突是有意生成的。md5()应该永远不会用于密码。你应该使用sha2家族的一个成员,沙-256或沙-512是很好的选择.

第三种脆弱性:

CSRF

我没有看到任何CSRF保护您的身份验证逻辑。我怀疑您的应用程序中的所有请求都容易受到CSRF的攻击。

票数 19
EN

Stack Overflow用户

发布于 2016-06-03 20:56:54

这个被接受的答案在一些事情上少了很多,也错了。下面是我在代码中看到的漏洞:

代码语言:javascript
复制
define('QUERY_SCRIPT', basename($_SERVER['PHP_SELF']));

正如其他地方所说的,这可以包含的不仅仅是脚本路径。使用$_SERVER['SCRIPT_NAME']__FILE__代替。

代码语言:javascript
复制
define('CP_HTTP_ROOT', ...

此常量用于将cookie路径设置为脚本路径。这并不是不安全的,但是用户需要单独登录到每个脚本。相反,使用会话(在下面讨论)并为您的应用程序设置一个基本路径。

代码语言:javascript
复制
UnlockSessionAndDestroyAllCokies()

我不知道这到底是怎么回事,但听起来不太好。只需在脚本的早期为每个请求启动会话。检查会话中现有的用户信息,以了解他们是否已经登录。

代码语言:javascript
复制
$pass = md5($_POST['pass']);

密码应该对每个散列都有一个唯一的盐,最好使用更好的散列算法。现在的 (PHP 5.5+)您应该使用 password_hash password_verify 来处理您的密码哈希细节。

代码语言:javascript
复制
mysql_query("SELECT id FROM cp_users WHERE name = '". addslashes($user)...

这是一个老问题,但今天不再支持mysql_函数。使用mysqli或PDO。使用不受支持的库的会使您打开未修补的漏洞。addslashes并不是防止SQL注入的完美保护。使用预准备语句,或者至少使用库的字符串转义函数。

代码语言:javascript
复制
if (isset($_POST['remember']) && $_POST['remember'] == 1) 
( 
    setcookie(COOKIE_USER, md5($user), COOKIE_LIVETIME, CP_HTTP_ROOT);
    setcookie(COOKIE_PASS, $pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 
) 

这是最大的问题。 cookies正在存储用户凭据。您将返回一个哈希用户名和哈希密码,并将其作为cookie值发送给响应。这些内容可以很容易地被第三方阅读和使用。由于这个脚本使用一个简单的散列,彩虹表将允许某人查找许多用户密码。但是,由于响应包含“安全”凭据,攻击者只需将它们传递到任何其他请求中即可登录。这不是“记住”用户的正确方式,也不是必要的。

用户与请求的连接只应在会话中处理。这就是他们的目的。请求和响应包含带有随机标识符的cookie。用户详细信息仅保留在服务器上,并链接到此标识符。(附带注意:有一个错误,这个块是用括号而不是大括号包装的。)

代码语言:javascript
复制
$_SESSION['Pass'] = $pass; 

现在,将用户的密码存储在的两个位置:数据库和会话存储。如果会话存储在数据库之外( PHP默认将它们存储在磁盘上),那么您现在有两种方法可以尝试窃取用户凭据。

代码语言:javascript
复制
if ($logined !== 1 && !empty($_COOKIE[COOKIE_USER]) ...
  if (($r = @mysql_query("SELECT * FROM cp_users WHERE MD5(name)='". addslashes($_COOKIE [COOKIE_USER ])."' AND pass = '". addslashes($_COOKIE [COOKIE_PASS])..

攻击者现在可以尝试登录,只需在请求中传递cookie标头,其中包含用户名和密码的md5散列,并在先前的响应中传递给它们。登录表单应该是获取用户凭据并将其登录的唯一位置。此表单(以及所有其他表单)应使用CSRF令牌。

代码语言:javascript
复制
UnlockSession();

同样,我不知道这是在做什么,但是在脚本的末尾,会话应该被写到存储中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2541230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档