初玩RFID

有段时间早晨去实验室比较早,但是我又没有门禁卡,只能默默的等别人来开门,而且听说办门禁卡很麻烦。看了下门外那个简陋的刷卡器,觉得自己买个读卡器复制一张应该不麻烦。

现在使用的比较多的智能卡主要分为

  • ID卡,只能存储一个ID
  • IC卡,可以存储ID和数据,常见的是Mifare1 S50卡
  • CPU卡

先记录下 M1 S50卡的结构

  • 分为16个扇区(0-15),每个扇区又分为4个区域块(0-63)
  • 每个扇区都有独立的一对密码keyA和keyB,负责控制对每个扇区数据的读写操作,keyA和keyB分布在每个扇区的第四块中
  • 第0扇区的第一个数据块,存储着IC卡的UID号,其他扇区可以存储其他的数据
  • 正常的卡的UID是只读的,不能出厂后再次修改,但是万能的淘宝上可以买到UID可写的白卡

需要的设备

  • ACR122U RFID读写器 淘宝或者阿里巴巴上可以买到,大约170元
  • 几张白卡,即UID区域可写的卡,一张大约2块钱
  • 需要复制的门禁卡

阅读全文...

bctf 部分writeup

又是一个和ctf一起度过的疲惫的周末。

QAQ

一个留言板,提交之后可以看到部分内容被过滤了,包括onscriptimg等,最终发现iframe标签没被过滤,而且可以利用的是srcsrcdoc属性,srcdoc使用html实体编码绕过。其中我遇到一个坑,就是开始认为&也被过滤了,而实际上是我没进行url编码,导致burp识别错误。

主办方的机器人一直不太稳定,第二天才真正的开始做这个题,xss探测结果是后台在http://104.199.132.251/4dm1n/show.php,cookies没啥用,页面源码也是只个列表,也没啥用。后来看到提示,说可以探测内网,想起使用webrtc,参考 http://www.wooyun.org/bugs/wooyun-2014-076685

阅读全文...

0ctf部分write up

首先不得不说这场比赛题目水平还是相当相当高的,毕竟是0ops团队。

Monkey

What is Same Origin Policy?

The flag is at http://127.0.0.1:8080/secret After you submitted a url, a monkey will browse the url. The monkey will stay 2 minutes on your page.
Try to find a string \$str so that (substr(md5(\$str), 0, 6) === '54d7ed').

首先这个题要计算md5,每次刷新页面都会变的,其实6位的md5组合并不多,理论上是$16^6$个,所以先计算出一些,保存起来,每次到文件中查找就好了。

import hashlib
for i in xrange(1000000000):
    print i, hashlib.md5(str(i)).hexdigest()

算了一会,觉得差不多了,就停了下来,生成了大约2G的文件。查询md5的时候,就使用cat md5.txt|grep xxxx

然后下面域名随便写了自己的一个域名,查看log确实会有一个访问,UA是Mozilla/5.0 0ctf by md5_salt,但是题目上是要访问127.0.0.1才行。

如果将自己的页面上加入js ajax访问127.0.0.1,会因为同源策略被拦截,访问失败。如果想跨域发送请求,需要对方网站设置Access-Control-Allow-Origin,但是没办法收到响应。

现在唯一能控制的就是自己的域名,能不能让自己的域名在爬虫访问的时候是正常的ip,然后js执行的时候变成127.0.0.1呢,这样域名仍然是不变的既可以跨域了。

后来在提示下找到了DNS Rebinding这个方法,页面加载后使用setTimeout增加js执行时间,然后在这个过程中修改域名解析到127.0.0.1,这个就要求DNS的TTL要尽可能的小,才能尽快的生效,一直在用的CloudXNS可以设置60s的TTL,已经足够了。

阅读全文...

jQuery选择器导致的xss问题

小伙伴发了某站的一个链接,xss payload在url的hash后面,然后页面弹框了,但是查看页面源代码,就只有jquery.jsjquery.fullpage.js,猜测是fullpage.js的问题,因为记得自己用fullpage.js的时候,hash部分会是#first#second,然后切换页面的时候会变,可能是fullpage.js处理不当导致的。使用Chrome的调试工具发现还并不是这样的。

QQ20160308-0@2x.png

js经过压缩,这里的d就是jQuery的$,也就是说$("<img src=# onerror=alert(1)")就是可以弹框的,使用页面上的js发现确实是这样的。

QQ20160308-1@2x.png

觉得这个问题在哪见过,后来在evi1m0的博客找到了,确实是jQuery的问题,在fullpage.js的GitHub里面也有提到,jQuery的bug ticket是 https://bugs.jquery.com/ticket/9521

开发者的建议就是

I agree that developers need to be aware of any case where they are
passing untrusted input to methods that can create HTML, such as $()
or $().html() or the DOM's .innerHTML property for that matter. We
cannot solve the problem inside jQuery because we cannot judge the
trustworthiness of the string being passed.

innerHTML可能会产生xss,这个好理解,主要是很多人并不知道$()也可能创建HTML。

sctf中的两道模板注入

FlagMan

使用GitHub Oauth登录,然后页面上就可以显示你的GitHub头像、用户名、用户id。常见的思路都想过了,发现不行,后来看到登录页面有个隐藏的Powered by Flask,联想起最近的Jinjia2模板注入,应该是在GitHub的真实姓名的位置。

http://blog.knownsec.com/2016/02/use-python-features-to-execute-arbitrary-codes-in-jinja2-templates/ 有一个POC

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{{ c.__init__.func_globals['linecache'].__dict__['os'].system('id') }}
{% endif %}
{% endfor %}

原理就是Jinjia2中可以访问空列表,然后[].__class__.__base__objectobject__subclasses__()就是所有继承object的类,依次类推,找到了一个导入了os模块的,然后取出来使用。如果能找到其他模块中导入了os也行,但是没有再去找。

阅读全文...