前言

最近在上课的时候用到了dvwa这个靶场,老师讲SQL注入时穿插讲了一下登录页面跟数据库的交互,之前也对这个靶场源码感兴趣,所以今天就来审一审代码,先从最简单的登录页面login.php开始,

因为我是自己审,完全没有经验,也没学过php,如果有错误各位师傅一定要指出来,万分感谢,是一个简单的登录界面,挑出一些重点来审一下,最重点的当然是跟MySQL的交互

dvwa GitHub地址:https://github.com/digininja/DVWA

原文章:http://plumstar.cn/2022/03/18/dvwa-deng-lu-ye-mian-dai-ma-shen-ji/

检测session信息代码

利用array_key_exists检测是否有session信息,若有则将获取的session传给$session_token变量,若为其他情况,则$_session_token传入为空

if( isset( $_POST[ 'Login' ] ) ) {//检测传入的Login是否已经设置并且非null
	// Anti-CSRF,写的已经很清楚了,检测session,抗CSRF攻击
	if (array_key_exists ("session_token", $_SESSION)) {
		$session_token = $_SESSION[ 'session_token' ];
	} else {
		$session_token = "";
	}

	checkToken( $_REQUEST[ 'user_token' ], $session_token, 'login.php' );

这一端是10-18行,检查session信息,抗CSRF攻击;array_key_exists函数用来 检查数组里是否有指定的键名或索引,用法:

array_key_exists(string|int $key, array $array): bool

数组里有键 key 时,array_key_exists() 返回 **true**。 key 可以是任何能作为数组索引的值。

username处理代码

username与数据库交互的一串代码;

输入的username传入变量$user中,用stripslashes函数进行一次反引用处理,isset函数和is_object函数对全局变量进行检测,并与数据库中全局变量进行交互,错误时会用trigger_error函数返回一个错误并提醒Fix the mysql_escape_string() call! This code does not work.

$user = $_POST[ 'username' ];
$user = stripslashes( $user );//stripslashes — 反引用一个引用字符串
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
//isset-检测后方数据是否设置并且是否为空
//is_object — 检测变量是否是一个对象
//trigger_error — 产生一个用户级别的 error/warning/notice 信息
//mysqli_real_escape_string — 根据当前连接的字符集,对于 SQL 语句中的特殊字符进行转义

ps:$GLOBALS["___mysqli_ston"]为全局变量,这里为了与数据库进行确认是否可连接

password处理代码

跟上方username的处理代码类似,就不再赘述;只不过加上了一串代码,用md5函数对$pass进行加密

$pass = $_POST[ 'password' ];
$pass = stripslashes( $pass );
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );//对$passj

检查数据库是否配置正确

	$query = ("SELECT table_schema, table_name, create_time
				FROM information_schema.tables
				WHERE table_schema='{$_DVWA['db_database']}' AND table_name='users'
				LIMIT 1");//定义$query变量为数据库查询语句,查询数据库内信息
	$result = @mysqli_query($GLOBALS["___mysqli_ston"],  $query );//mysqli_query — 对数据库执行一次查询,查询语句为$query定义的语句
	if( mysqli_num_rows( $result ) != 1 ) {//mysql_num_rows — 取得结果集中行的数目,获取刚才查询的结果并且进行判断
		dvwaMessagePush( "First time using DVWA.<br />Need to run 'setup.php'." );
		dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'setup.php' );
	}
//判断不为1则返回First time using DVWA.Need to run 'setup.php'.并且羊肉面跳转到setup.php页面

数据库配置正确后的登录操作

	$query  = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";//定义数据库查询语句
	$result = @mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '.<br />Try <a href="setup.php">installing again</a>.</pre>' );//执行$query定义的SQL语句与全局变量进行比对或者错误时返回错误信息并且退出脚本
	//die函数等同于exit()返回一条数据并退出脚本
	//mysqli_error —返回最后一个错误的字符串描述
	//mysqli_connect_error --返回最后一个连接错误的描述
	if( $result && mysqli_num_rows( $result ) == 1 ) {//登录成功    
		dvwaMessagePush( "You have logged in as '{$user}'" );//返回You have logged in as "user"信息
		dvwaLogin( $user );//以$user身份登录
		dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'index.php' );//以DVWA_WEB_PAGE_TO_ROOT身份跳转到index.php页面
	}

	// Login failed
	dvwaMessagePush( 'Login failed' );//输出Login failed 提示登录错误
	dvwaRedirect( 'login.php' );//挑战回login.php页面重新登录
}

写在最后

代码审计一直是作为一个学习者需要掌握的能力,这系列文章会一直持续更新,初学者可能有写的错误的时候,请大家看到帮我指出,万分感谢!