python自动化处理审计_自动化代码审计

0x00 前言

大概去年的时候就想写这样一篇文章,最近看到老外写的一个ppt,于是就有了这篇文章,随便看看就好,价值不是很大。

测试一个应用程序是否存在漏洞的思路总结起来无非 黑盒 和白盒 ,或者两者结合。黑盒的思路简单概括即是 通过异常输入判断程序是否存在漏洞,白盒即是 通过审阅程序代码来了解程序逻辑来判断漏洞。我这里想说的思路是结合两者的特性来完成整个过程的自动化。

如果要你用一句话来概括一下白盒的过程改怎么评价,如果让我来评价就是“了解逻辑a 在到达 逻辑 b的中间发生了什么。”打个比方, 变量$s 在到达 get_one 函数之前发生了什么。

#1.php

$s = $_GET['s'];

if(is_numeric($s)){

echo get_one("select id from admin where id=".$s);

}else{

echo "error";

}

上面的代码转换成黑盒的方式就是 http://xxx.com/1.php?=[fuzz] 通过程序对于输入的反馈来判断。整个过程我们可以变换成以下形式,打个比方 我们输入 id=23,那么程序的执行过程就是。

$s = 23;

is_numeric($s)==True;

echo get_one("select id from admin where id=23");

这篇文章我们简单谈论一下,将输入映射到程序逻辑这个过程的自动化。

0x01 编程语言的解析

你思考过解释器或者编译器如何理解程序的逻辑的吗,程序会先经过词法分析解析,根据语法将程序分割。然后进行语法分析,根据程序的逻辑过程形成树的形式。之后是 语义分析 ,对程序的数据类型与一些语法进行校验。一个例子

while b!=0

if a>b

a:= a-b

else

b:= b-a

return a

现在读者应该对编程语言的解析有了一些概念,我们的输入的字符串最终就是通过这样一种树的形式,经过一道一道的逻辑。

0x02 有限状态机

思考一下,我们的程序从输入开始,经由一个逻辑 转移到下一个不同的逻辑,其中会经过许多变换最终可能变成一种完全不同的形式,是不是就像一个有限状态机的过程?我们现在要做的就是将源代码最终表示为有限状态机的形式。我们要做的简单来说,或者更符合直觉的解释就是,将我们想搞清楚的 逻辑a 到 逻辑b 的过程 抽象成类似一个流水线一样的东西,我们可以将字符串丢进去,然后工人会不停的判断,修改,最终得到我想要的。

0x03 简单的例子

现在我们会开始慢慢解析整个过程,首先需要的就是将 原生的程序的代码解析成语法树,下面是库调用。phply是一个老外写的python版本php解释器。

from phply.phpparse import parser

from phply.phpast import *

from phply import pythonast, phplex

import ast,sys,phply,pprint

我们简单的解析一个php代码

example = "{C}"

lexer = phplex.lexer.clone()

output = parser.parse(example, lexer=lexer)

for i in output:

print i

out:

Assignment(Variable('$s'), 'hello world', False)

Echo([Variable('$s')])

我们可以很简单的看出第一句是将字符串hello world分配给$s,接着第二行就是函数调用。其中有什么不同,难道只是字符串变长了?No~ 现在程序的操作都变成了一个个可操作的对象,我们又可以将它表示成有限状态机的形式。

我们来看另一个存在xss漏洞的例子

def tf(string):

lexer = phplex.lexer.clone()

output = parser.parse(string, lexer=lexer)

return output

example = ""

for i in tf(example):

print i

out:

Assignment(Variable('$a'), ArrayOffset(Variable('$_GET'), 's'), False)

Echo([Variable('$a')])

So,一切现在看起来清晰可见,我们接下来要做的是什么?表示成有限状态机?听起来是不是想打我,那换种说法,我们需要的是让变量能够转变成我们的输入,完成 http://xxx.com/1.php?=23 到 $s = $_GET['id'] 的映射,然后我们需要让程序一步步的执行。然后看最终执行到哪。那么,How? 刚才我们已经说过,现在的程序的每个逻辑都是我们可以操作的对象,所以只需要替换他就行了。

seq = []

for i in tf(example):

if 'expr' in i.__dict__.keys():

if i.__dict__['expr'].__dict__['node']==Variable('$_GET'):

seq.append(tf("")[0])

continue

seq.append(i)

for i in seq:

print i

Assignment(Variable('$a'), 'hello fuck', False)

Echo([Variable('$a')])

那么接下开我们需要做的就是执行他。我们会建立一个eval的函数,让python的解释器来执行php的代码。

def php_eval(nodes):

body = []

for node in nodes:

stmt = pythonast.to_stmt(pythonast.from_phpast(node))

body.append(stmt)

code = ast.Module(body)

comp = compile(code, '', mode='exec')

eval(comp,globals())

请注意,既然说了最终是由python的解释器来执行,那么像echo这种php有的函数python就没有,我们就需要自己实现一下,或者你也可以传递给php执行。因为我没转php所以就简单写一个实现。

def echo(*objs):

for obj in objs:

sys.stdout.write(str(obj))

最后,执行。

php_eval(seq)

out:

hello fuck

这样我们就可以用程序自动HOOK 逻辑a 和逻辑b,然后通过fuzz挖掘其是否存在漏洞。

0x04 Bypass

是不是总觉得少些什么,挖掘漏洞的过程之中会遇到许多许多奇葩的逻辑,我们不能只是单纯的把他取出来,改下变量,然后看运气。我们需要一些更加复杂的东西。现在我举例一个真实的例子, 这是以前做代码审计的时候遇到的,代码我省略了很多。

$string = $_POST['string'];

$string = str_replace("select","select",$string)

$string = str_replace("*","",$string)

get_one($string);

我们只需要 先注入一个 string , 去触发规则,然后再根据写好的混淆规则对sql做变形,那么就可以达到自动bypass的目的。

打个比方,我们可以hook程序的 str_replace ,然后再写一个混淆规则 比如

if replace "*" to "":

* == 混淆字符

0x05 结语

最近比较忙,很多地方没办法写详细,以后再说吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值