代码审计思路&案例

前言

代码审计(Code Audit)顾名思义就是通过阅读源代码,从中找出程序源代码中存在的

缺陷或安全隐患,提前发现并解决风险,这在甲方的SDL建设中是很重要的一环。而在渗透测试中,可以通过代码审计挖掘程序漏洞,快速利用漏洞进行攻击达成目标。

审计思路

常见的审计思路有:
 

1.寻找敏感功能点,通读功能点代码;

  优点: 精准定向挖掘,利用程度高;

  缺点:命名不规范的代码容易被忽略,导致失去先机。

2.根据敏感关键字回溯参数传递过程;

  优点:通过搜索敏感关键字可快速定位可能存在的漏洞,可定向挖掘,高效、高质量;

  缺点:对程序整体架构了解不够深入,在漏洞定位时比较耗时,逻辑漏洞覆盖不到。

3.直接通读全文代码;

  优点:对整体架构熟悉,了解程序的数据流处理、配置文件、过滤函数等;

  缺点:耗时长,需要足够的时间熟悉整体架构。

审计方法

按照是否使用(半)自动化工具分有工具扫描、人工审计和两者相结合的几种审计方式,笔者比较喜欢硬刚,毕竟正常挖业务层面漏洞没有那么复杂,不太需要对底层的一些特性了解的很清楚。

按照数据流向可分为正向审计和逆向审计,正向审计即从功能入口点进行跟踪,一直到数据流处理结束;逆向审计即现根据一些关键词搜索,定位到可能存在风险的关键词/函数,再反推到功能入口,看整个处理过程是否存在漏洞。

成功案例

案例一:一个任意文件下载漏洞引起的代码审计

在一次授权测试中,找到一处任意文件下载漏洞,正常思路先下载网站的配置文件,看看数据库是否可以外联。

不幸的是不可以外联(其实现在能外联的也很少了),幸运的是在配置文件中收集到了一个域用户,这是意外之喜。

接着下载Download.aspx文件看看内容:

我们知道, .net是编译型语言,在aspx中一般是没有服务代码的,这里看到使用了Inherits来继承后端代码。

Inherits是啥?

MSDN官方解释:定义供页继承的代码隐藏类。它可以是从Page类派生的任何类。此特性与CodeFile

特性一起使用,后者包含指向代码隐藏类的源文件的路径。

通俗一点就是代码都在这个Inherits指向的dll中了,那么我们下载到dll文件,就可以对后端代码进行一波窥探了,于是构造下载XXXXXX.Web.dll,文件下载到本地后,IL Spy打开就是一顿肉眼观察。

大致看了一下目录,有Upload字样,优先级直线上升,先进去看看:

 
  1. public void uploadFile() {

  2. string formStringParamValue = SWFUrlOper.GetFormStringParamValue("path");

  3. string formStringParamValue2 = SWFUrlOper.GetFormStringParamValue("fn");

  4. bool flag = SWFUrlOper.GetFormStringParamValue("small").ToLower() == "true";

  5. ......

  6. string[] array = new string[]

  7. {

  8. "jpg",

  9. "gif",

  10. "png",

  11. "bmp"

  12. };

  13. string formStringParamValue3 = SWFUrlOper.GetFormStringParamValue("data");

  14. try {

  15. System.Web.HttpPostedFile httpPostedFile = base.Request.Files["Filedata"];

  16. string b = string.Empty;

  17. string text = string.Empty;

  18. if (httpPostedFile.ContentLength > 0) {

  19. text = httpPostedFile.FileName;

  20. if (text.IndexOf(".") != -1) {

  21. b = text.Substring(text.LastIndexOf(".") + 1, text.Length - text.LastIndexOf(".") - 1).ToLower();

  22. }

  23. SWFUploadFile sWFUploadFile = new SWFUploadFile();

  24. if (flag) {

  25. sWFUploadFile.set_SmallPic(true);

  26. sWFUploadFile.set_MaxWith((formIntParamValue == 0) ? sWFUploadFile.get_MaxWith() : formIntParamValue);

  27. sWFUploadFile.set_MaxHeight((formIntParamValue2 == 0) ? sWFUploadFile.get_MaxHeight() : formIntParamValue2);

  28. }

  29. sWFUploadFile.set_IsWaterMark(isWaterMark);

  30. int num = 0;

  31. string text2 = sWFUploadFile.SaveFile(httpPostedFile, formStringParamValue, formStringParamValue2, ref num);

  32. ...

  33. }

38行进行了文件保存,之前没有对文件的内容、后缀等有任何过滤,开开心心挖到任意文件上传。二话不说本地构造上传个shell。

 
  1. <form name="form" method="post" action="http://xxxx.com/cms/SWFUpload.aspx" enctype="multipart/form-data" >

  2. <input type="file" name="Filedata">

  3. <input type="submit" name="Submit" value="upload" >

  4. </form>

假如这里代码被混淆的话,可以使用de4dot进行反混淆,de4dot支持10几种混淆方式的反混淆:

Dotfuscator

.NET Reactor

Xenocode

CryptoObfuscator

SmartAssembly

......

比如使用Dotfuscator混淆过的DLL是这样的:

使用de4dot反混淆:

CMD命令行执行: de4dot.exe ADD.dll

看下效果:

代码已经基本恢复到可读状态了,其他高级用户请参考github上的介绍。

案例二:某个开源系统的代码审计

授权渗透时发现只有一个登录框,遇到这种情况一般只能拼字典进行爆破了,还好客户使用的是一套开源系统二次开发,可以down到代码进行分析一波。

拿到代码看了一下结构,是thinkphp的二开,遵循MVC模型代码那是一个层次分明。

因为目标只有登录框,所以这里我关注的重点除了文件上传、SQL注入,又多了一个绕过登陆的想法了,no代码no哔哔~~

Upload太刺眼了,忍不住进去分析一下。

 
  1. class UploadController extends ComController {

  2. ......

  3. private function saveimg($file) {

  4. $uptypes = array(

  5. 'image/jpeg',

  6. 'image/jpg',

  7. 'image/jpeg',

  8. 'image/png',

  9. 'image/pjpeg',

  10. 'image/gif',

  11. 'image/bmp',

  12. 'image/x-png'

  13. );

  14. $max_file_size=2000000; //上传文件大小限制,单位BYTE

  15. $destination_folder = 'Public/attached/'.date('Ym').'/'; //上传文件路径

  16. if ($max_file_size < $file["size"]) {

  17. echo "文件太大!";

  18. return null;

  19. }

  20. if (!in_array($file["type"], $uptypes)) {

  21. echo "文件类型不符!".$file["type"];

  22. return null;

  23. }

  24. if (!file_exists($destination_folder)) {

  25. mkdir($destination_folder);

  26. }

  27. $filename = $file["tmp_name"];

  28. $image_size = getimagessize($filename);

  29. $pinfo = pathinfo($file["name"]);

  30. $ftype = $pinfo['extension'];

  31. $destination = $destination_folder.time().".".$ftype;

  32. if (file_exists($destination) && $overwrite != true) {

  33. echo "同名文件已经存在了";

  34. return null;

  35. }

  36. if (!move_uploaded_file($filename, $destination)) {

  37. return null;

  38. }

  39. return "/".$destination;

  40. }

  41. ......

只对文件MIME类型进行了检测,做安全的都爱这样的开发工程师,比心~

不过这里继承了ComController,里面有身份认证,不能直接getshell了...呜呜呜,还要突破登录后台才行。

跟进ComController看下认证检查过程。

 
  1. class ComController extends BaseController {

  2. public $USER;

  3. public function _initialize() {

  4. C(setting());

  5. $user = cookie('user');

  6. $this->USER = $user;

  7. $url = U("login/index");

  8. if (!$user) {

  9. header("Location: {$url}");

  10. exit(0);

  11. }

  12. $Auth = new Auth();

  13. $allow_controller_name=array('Upload'); //放行控制器名称

  14. $allow_action_name = array(); //放行函数名称

  15. if (!$Auth->check(CONTROLLER_NAME.'/'.ACTION_NAME, $this->USER['uid'])&&!in_array(CONTROLLER_NAME, $allow_controller_name) && !in_array(ACTION_NAME, $allow_action_name)) {

  16. $this->error('没有权限访问本页面!');

  17. }

  18. $user = member(intval($user['uid']));

  19. $this->assign('user', $user);

嗯,我可能深深爱上了这个开发工程师了,从cookie中获取认证信息,并赋值给$user对象,那么我们就可以操控用户登录啦,在配合后台的任意文件上传,美滋滋~

失败案例

总结

相对于甲方不同,渗透测试中代码审计更多的是挖掘可利用的漏洞或利用链进行攻击,尽可能的获取更高的权限为目的。

个人觉得渗透测试时关注的漏洞优先级:

命令执行 > 代码执行 > 文件上传 > 文件包含 > SQL注入 > 文件下载 > 逻辑漏洞 > SSRF > XSS ....

代码审计除了需要了解漏洞的原理、熟悉常见的编程语言、常见的危险函数、常见的协议、渗透技巧外,还需要一些开发调试工具(IDEA、PHPStrom、PyCharm ...),以上内容有不正之处,还请大家斧正。

注:

de4dot项目地址: 

https://github.com/0xd4d/de4dot/

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值