Wechall刷题(二) Training: MySQL I 总结

来源:互联网 发布:软件项目管理流程图 编辑:程序博客网 时间:2024/06/10 11:09

Training: MySQL I 总结

题目

题目总结分为四个部分

  1. 解题思路及部分答案
  2. 个人疑惑以及疑惑解答
  3. 常见的SQL注入语句
  4. 收获:通过本地模拟环境测试

1.解题思路及部分答案

这是一个简单的SQL注入题目,对于初初初学者学者的我来说连源代码都看不懂,所以就一点一点详细道来吧!

  • 首先源代码解析:

    /* TABLE STRUCTURECREATE TABLE IF NOT EXISTS users (userid    INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,username  VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,password  CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL) ENGINE=myISAM;

    这部分就是创建一个表users,表的三个列分别为userid,username,password

  • # Username and Password sent?if ( ('' !== ($username = Common::getPostString('username'))) && (false !== ($password = Common::getPostString('password', false))) ) {      auth1_onLogin($chall, $username, $password);}

    这部分是判断用户名和密码是否已经发送给服务器,其中的Common::getPostString是调用已有函数,功能为从表单中获取字符串信息;auth1_onLogin为下边的自定义函数,功能为验证用户名和密码

  • /*** Get the database for this challenge.* @return GDO_Database*/function auth1_db(){      if (false === ($db = gdo_db_instance('localhost', WCC_AUTH_BYPASS1_USER, WCC_AUTH_BYPASS1_PASS, WCC_AUTH_BYPASS1_DB))) {              die('Database error 0815_1!');      }      $db->setLogging(false);      $db->setEMailOnError(false);      return $db;}

    这部分代码其实我还不是很清楚,我认为是初始化一个数据库实例,用来后续操作,这部分不影响完成题目

  • /*** Exploit this!* @param WC_Challenge $chall* @param unknown_type $username* @param unknown_type $password* @return boolean*/function auth1_onLogin(WC_Challenge $chall, $username, $password){      $db = auth1_db();      $password = md5($password);      $query = "SELECT * FROM users WHERE username='$username' AND password='$password'";      if (false === ($result = $db->queryFirst($query))) {              echo GWF_HTML::error('Auth1', $chall->lang('err_unknown'), false); # Unknown user              return false;      }      # Welcome back!      echo GWF_HTML::message('Auth1', $chall->lang('msg_welcome_back', htmlspecialchars($result['username'])), false);      # Challenge solved?      if (strtolower($result['username']) === 'admin') {              $chall->onChallengeSolved(GWF_Session::getUserID());      }      return true;}

    这部分就是之前提到的自定义函数,用来处理表单提交的数据。函数与表单之间通过参数“username”和“password”传递数据,这里只需要知道从html表单中输入的username和password就可以代入到这里的query语句中就可以了。

    接着result=db->queryFirst($query)处理MySQL语句并且将结果返回给result,如果查询结果不是false,说明结果存在。

    $result[‘username’]) === ‘admin’判断用户是否是admin,如果是说明管理员登录。

    完成登陆过程。

  • 然后说明注入过程:这里要想办法输入username和password使得执行query语句的结果存在并且用户名为Admin。但是由于我们不知道真实的admin的密码,所以我们想办法绕过password。即我们可以减少select的限制条件,通过将query中AND及其后边的语句在MySQL语句中注释掉,就可以将query改写为:

    SELECT * FROM users WHERE username='admin'

    于是需要知道MySQL中的注释语法:MySQL注释

    这里我们选择单行注释,即’#’和’–’

  • 答案 :那么构造username分别为:username=admin’#和username=admin’– (注意这里–后边要加括号,原因见MySQL注释);password不填

2.个人疑惑及其解答

解题思路为“注释”,于是我认为下边的填写才正确;

username=admin' ";#

如果这样填写,源代码中的query就变成了

$query = "SELECT * FROM users WHERE username='admin'";#' AND password='$password'";

如此一来既保证了语法正确,而且还将#后边的内容注释掉了(因为#也是php语句的注释)。但结果并不是这样的,我们将不同的username输入之后得到的结果如下:

test

我本以为第三种情况才是正确的,因为这样得到的&query才是完整的,既有封闭的“”,还有分号作为php结束的标志,完全符合语句的标准。而像第一种情况得到的&query后边缺少分号,难道不会报语句完整性错误吗??

通过请教他人和查阅资料,发现php语句可以没有最后的分号作为结尾(但是前提是后边的分块的结尾符号,这里后边的注释语句。。。不知是否可行),这样的话,第一种情况就可以说的过去了;

“php变量的内容不能阶段php语句”

这句话点醒了为什么第三种情况不能成功注入了,这里的MySQL语句在注释之前多了一个”使得语法错误,不能通过。

这里很重要的一点是,输入的username中的注释都只能注释掉MySQL中的后边句子,而不能截断原来的php语句!!!

下边是MySQL SQL 和 PHP的注释语法

MySQL注释 SQL注释 PHP注释1 PHP注释2

3.常见的SQL注入语句测试

’ or ‘1’=’1
’ or 1=1 –
‘or’=’0’
“or 1=1 –
or 1=1 –
‘or’ a ‘=’ a
“or” a “=” a

师傅所传授!暂时还没有实践使用,先记下来

4.在解答疑惑的过程中的收获

师傅是这样解答我的疑惑的,他通过搭建一个本地的php的web环境,通过样例,给定输入得到输出,从而证明并解释了变量中的注释符号不能截断php的现象。所以,这样的解决问题的思路还是很值得学习的,加油!

原创粉丝点击