[其他] Iscc 2017 ctf web Simple sqli 详细分析

[复制链接]
查看6891 | 回复0 | 2017-5-29 00:06:26 | 显示全部楼层 |阅读模式
概述
这道题目的解法并不唯一,但我个人感觉这种方法感觉是最触及核心的,也是见多识广的人应该了解的方法。
开始实践,细细琢磨
首先看到的就是这个验证码,
substr(md5(captcha), 0, 3)=9ef
关键在于他真的很’智能’真的是每次都变,不是闹着玩的
大概的意思是他会把captcha这个数据md5,然后取前3位,和等于号后面的值比较,相等就行了,然后好奇capcha到底怎么获得,看了一下元素,发现他是真的有这个参数的
%E7%BB%95%E8%BF%871.jpg
不管那么多只能写一个脚本爆破md5的值,毕竟不能逆推只能比对,脚本如下:
1
2
3
4
import hashlib
for i in xrange(100000):
    if hashlib.md5(str(i)).hexdigest().startswith('efd'):
        print i

开始注入:
首先我们尝试最一般的 username=admin&password=admin&captcha=8029
报 password error
说明似乎用户名被蒙对了
换一个随便的用户名 username=a&password=admin&captcha=9612
报 username error
说明登录验证是分两步进行的,首先是检验用户名是否正确,如果用户名正确那么验证密码正确与否,密码正确那么登陆成功,密码错误登录失败。但是用户名不正确,就不会检验密码,直接登录失败。
补充1
php常见的登录验证方式就是两种
1.select from foobar where username=’’ and password=’’
查寻语句为真就登陆成功否则登录失败
2.select password from foobar where username=’’(这个username就是我们输
入的值)
如果找不到那么用户名错误
否则
如果查到的密码和输入的password/或者是输入的经过md5加密后的值相等那么登陆成功
否则输出密码错误
我们可以去验证一下是不是属于第二种情况(依据是他是否只select password还是select

%E7%BB%95%E8%BF%872.jpg

%E7%BB%95%E8%BF%874.jpg
这里面会报两个password error 因为union select @@version 也在查询到的数据中,他是对查询到的数据一条一条和密码去匹配,结果发现我们的两条数据和输入的密码都不一样,所以会报两个password error
我们来本机测试一下
%E7%BB%95%E8%BF%875.jpg
两条数据清晰可见,union select 很多时候就是用来填充或者引入别的数据到同一个表里
那么我们只要用union select 去构造一个数据在存放查询得到的password 的那个表中,也就是上图的5.6.17的位置,再输入我们设定好的password,那样依赖他循环遍历对比的特点,就可以绕过密码登陆成功,我们试一下:
%E7%BB%95%E8%BF%876.jpg
%E7%BB%95%E8%BF%877.jpg
%E7%BB%95%E8%BF%878.jpg
咦,怎么回事呢,因为他验证用的是我上面说的另一种方法,把我们输入的值得md5的结果和数据库中的对比,也就是说数据库中存储的全都是md5的值,因此我们修改一下我们的payload
%E7%BB%95%E8%BF%879.jpg

%E7%BB%95%E8%BF%8711.jpg
完全符合我们的猜想,第一个用户名admin的真实密码无法和我们构造的假密码去匹配,所以第一个是错的,然后第二个恰恰使我们构造的假密码,绕过成功!!
补充2
登录验证类似于这样
[mw_shl_code=php,true]<?php
$servername = "localhost";
$username = "php";
$password = "##############";
$database = "php";
if($_POST[user] && $_POST[pass]) {
    $conn = mysqli_connect($servername, $username, $password, $database);
    if ($conn->connect_error) {
        die("Connection failed: " . mysqli_error($conn));
}
$user = $_POST[user];
$pass = md5($_POST[pass]);
$sql = "select pw from php where user='$user'";
$query = mysqli_query($conn,$sql);
if (!$query) {
    printf("Error: %s\n", mysqli_error($conn));
    exit();
}
$row = mysqli_fetch_array($query);
//echo $row["pw"];
if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
    echo "<p>Logged in! Key: ################################ </p>";
}
else {
    echo("<p>Log in failure!</p>");
  }
}
?>[/mw_shl_code]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

匿名
御结冰城 该用户已被删除